### Description

#27647 has introduced filtering for invalid schemas in Hive hook based on the characters `;` and `!`. I'm wondering if a more generic filtering could be introduced, e.g. one that adheres to the regex `[^a-z0-9_]`, since Hive schemas (and table names) can only contain alphanumeric characters and the character `_`.

Note: since the Hive metastore [stores schemas and tables in lowercase](https://stackoverflow.com/questions/57181316/how-to-keep-column-names-in-camel-case-in-hive/57183048#57183048), checking against `[^a-z0-9_]` is probably better than `[^a-zA-Z0-9_]`.

### Use case/motivation

Ensure that Hive schemas used in `apache-airflow-providers-apache-hive` hooks contain no invalid characters.

### Related issues

_No response_

### Are you willing to submit a PR?

- [X] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)

part_specs: list[Any], partition_key: str | None, filter_map: dict[str, Any] | None
    ) -> Any:
        """
        Helper method to get max partition of partitions with partition_key
        from part specs. key:value pair in filter_map will be used to
        filter out partitions.
        :param part_specs: list of partition specs.
        :param partition_key: partition key name.
        :param filter_map: partition_key:partition_value map used for partition filtering,
                           e.g. {'key1': 'value1', 'key2': 'value2'}.
                           Only partitions matching all partition_key:partition_value
                           pairs will be considered as candidates of max partition.
        :return: Max partition or None if part_specs is empty.
        """
        if not part_specs:
            return None
        
        if partition_key not in part_specs[0].keys():
            raise AirflowException(f"Provided partition_key {partition_key} is not in part_specs.")
        is_subset = None
        if filter_map:
            is_subset = set(filter_map.keys()).issubset(set(part_specs[0].keys()))
        if filter_map and not is_subset:
            raise AirflowException(
                f"Keys in provided filter_map {', '.join(filter_map.keys())} "
                f"are not subset of part_spec keys: {', '.join(part_specs[0].keys())}"
            )
        candidates = [
            p_dict[partition_key]
            for p_dict in part_specs