private function query(string $function, array $parameters, bool $returnsGeometry) : array
    {
        $queryParameters = [];

        foreach ($parameters as $parameter) {
            if ($parameter instanceof Geometry) {
                if ($parameter->isEmpty()) {
                    $queryParameters[] = 'ST_GeomFromText(?, ?)';
                } else {
                    $queryParameters[] = 'ST_GeomFromWKB(?, ?)';
                }
            } else {
                $queryParameters[] = '?';
            }
        }

        $query = sprintf('SELECT %s(%s)', $function, implode(', ', $queryParameters));

        if ($returnsGeometry) {
            $query = sprintf('
                SELECT
                    CASE WHEN ST_IsEmpty(g) THEN ST_AsText(g) ELSE NULL END,
                    CASE WHEN ST_IsEmpty(g) THEN NULL ELSE ST_AsBinary(g) END,
                    ST_GeometryType(g),
                    ST_SRID(g)
                FROM (%s AS g) AS q
            ', $query);
        }

        return $this->executeQuery($query, $parameters);
    }