public function executeParams(string $sql, array $params, array $paramTypes = [], array $resultTypes = [])
    {
        if (!$this->isConnected()) {
            $this->connect();
        }
        $stringParams = [];
        foreach ($params as $key => $value) {
            if (isset($paramTypes[$key])) {
                $stringParams[$key] = $this->getTypeConverter($paramTypes[$key])->output($value);
            } else {
                $stringParams[$key] = $this->getTypeConverterFactory()
                    ->getConverterForPHPValue($value)
                    ->output($value);
            }
        }

        $result = @pg_query_params($this->getResource(), $sql, $stringParams);
        if (false === $result) {
            throw new exceptions\InvalidQueryException(pg_last_error($this->getResource()));
        }

        switch (pg_result_status($result)) {
            case PGSQL_COMMAND_OK:
                $rows = pg_affected_rows($result);
                pg_free_result($result);
                return $rows;

            case PGSQL_COPY_IN:
            case PGSQL_COPY_OUT:
                pg_free_result($result);
                return true;

            case PGSQL_TUPLES_OK:
            default:
                return new ResultSet($result, $this->getTypeConverterFactory(), $resultTypes);
        }
    }