"""Utility functions for getting Snowflake tables meta.""" from collections import namedtuple from garcon_contrib.snowflake import garcon_snowflake from snowflake_etl.conf import config SFTable = namedtuple('SFTable', ['db', 'schema', 'name']) def format_meta(sf_table, columns): """Format columns meta. Args: sf_table (SFTable): target table to format schema for. columns (list(tuple)): columns meta as fetched by DESC. Returns: dict: json-serializable dict """ def to_bool(x): return x and x == 'Y' def _id(x): return x meta_field_names = ( 'column_name', 'data_type', 'kind', 'is_nullable', 'column_default', 'primary_key?', 'unique_key?', 'check', 'expression', 'comment') assert (len(meta_field_names) == len(columns[0])), 'Number of column\'s fields do not match' # name -> value mapper fields_to_dump = { 'column_name': _id, 'data_type': _id, 'is_nullable': to_bool, 'column_default': _id } fmt_columns = [ dict( (name, fields_to_dump[name](value)) for name, value in zip(meta_field_names, column) if name in fields_to_dump) for column in columns ] return { 'database': sf_table.db, 'schema': sf_table.schema, 'table': sf_table.name, 'columns': fmt_columns } def fetch_meta(sf_table): """Fetch a table columns meta. Args: sf_table (SFTable): target table to fetch schema for. Returns: list(tuple): columns meta. """ sql = config.SF_DEFAULT_QUERIES['describe_table'].format( db=sf_table.db, schema=sf_table.schema, table=sf_table.name) meta = garcon_snowflake.execute_with_py_conn( sql, garcon_snowflake.FetchEnum.ALL, sf_config=config.SF_CONFIG)['results'] return meta def get_table_schema(db, schema, table): """Get Snowflake table schema. Args: db (str): table's database. schema (str): table's schema. table (str): table itself. Returns: dict: table schema. """ sf_table = SFTable(db, schema, table) meta = fetch_meta(sf_table) return format_meta(sf_table, meta)