def get_physical_table_metadata( database: Database, table_name: str, schema_name: Optional[str] = None, ) -> List[Dict[str, Any]]: """Use SQLAlchemy inspector to get table metadata""" db_engine_spec = database.db_engine_spec db_dialect = database.get_dialect() # ensure empty schema _schema_name = schema_name if schema_name else None # Table does not exist or is not visible to a connection. if not (database.has_table_by_name(table_name=table_name, schema=_schema_name) or database.has_view_by_name(view_name=table_name, schema=_schema_name)): raise NoSuchTableError cols = database.get_columns(table_name, schema=_schema_name) for col in cols: try: if isinstance(col["type"], TypeEngine): db_type = db_engine_spec.column_datatype_to_string( col["type"], db_dialect) type_spec = db_engine_spec.get_column_spec( db_type, db_extra=database.get_extra()) col.update({ "type": db_type, "type_generic": type_spec.generic_type if type_spec else None, "is_dttm": type_spec.is_dttm if type_spec else None, }) # Broad exception catch, because there are multiple possible exceptions # from different drivers that fall outside CompileError except Exception: # pylint: disable=broad-except col.update({ "type": "UNKNOWN", "type_generic": None, "is_dttm": None, }) return cols
def check_extra(self, database: Database) -> None: # pylint: disable=no-self-use # this will check whether json.loads(extra) can succeed try: extra = database.get_extra() except Exception as ex: raise Exception( _("Extra field cannot be decoded by JSON. %{msg}s", msg=str(ex))) # this will check whether 'metadata_params' is configured correctly metadata_signature = inspect.signature(MetaData) for key in extra.get("metadata_params", {}): if key not in metadata_signature.parameters: raise Exception( _( "The metadata_params in Extra field " "is not configured correctly. The key " "%{key}s is invalid.", key=key, ))