Please write a markdown document that describes the following PHP function.

public function query($permission, $sql, $values = null)
 {
 try {
 $this->check\_permission($permission); // throws exception if missing permission
 $stmt = $this->db->query(
 $sql,
 $values
 );
 if ($stmt instanceof dbError) {
 throw new Exception($stmt->getCode());
 }
 $rows = $stmt->fetchAll();
 if ($rows == false || $rows == null)
 throw new Exception('No Data Found', $this::EXCEPTION\_DATA);
 try {
 return $this->htmlspecialchars\_array($rows);
 } catch (Exception) {
 return $rows;
 }
 } catch (Exception | dbError | PDOException | Throwable $ex) {
 throw new Exception($ex->getMessage(), $ex->getCode());
 }
 }
Here is the markdown document describing the PHP function:
```
Query Function
================

### Description

Executes a SQL query on the database with the given permission, SQL statement, and optional values.

### Parameters

* `$permission`: The required permission to execute the query.
* `$sql`: The SQL statement to execute.
* `$values`: An optional array of values to bind to the SQL statement.

### Returns

An array of results from the query, with each value HTML-escaped using `htmlspecialchars`. If an error occurs, an `Exception` is thrown.

### Throws

* `Exception`: If the permission is missing, the query fails, or no data is found.
* `dbError`: If the database query fails.
* `PDOException`: If a PDO exception occurs.
* `Throwable`: If any other error occurs.

### Flow

1. Checks if the user has the required permission using `check_permission`. If not, an `Exception` is thrown.
2. Executes the SQL query using the database connection, binding the optional values.
3. If the query fails, an `Exception` is thrown with the error code.
4. Retrieves the query results using `fetchAll`.
5. If no data is found, an `Exception` is thrown with a specific error code.
6. Attempts to HTML-escape the results using `htmlspecialchars_array`. If this fails, the original results are returned.
7. Catches any exceptions that occur during the process and re-throws them
This function allows you to query the database using the given permission and SQL statement. It will throw an exception if the given permission is missing.

The function then proceeds to create a PDOStatement object and executes the given SQL statement with the given values. If an exception is thrown, it will be caught and a new Exception will be thrown with the original exception's message and code.

If the query succeeds, it will return an array of htmlspecialchars'd rows. If an exception is thrown, it will return the rows unchanged.