public function execute(array $params = [], array $resultTypes = [])
    {
        if (!$this->queryId) {
            throw new exceptions\RuntimeException('The statement has already been deallocated');
        }

        if (!empty($params)) {
            $this->values = [];
            foreach (array_values($params) as $i => $value) {
                $this->bindValue($i + 1, $value);
            }
        }

        $stringParams = [];
        foreach ($this->values as $key => $value) {
            if (isset($this->converters[$key])) {
                $stringParams[$key] = $this->converters[$key]->output($value);
            } else {
                $stringParams[$key] = $this->connection->getTypeConverterFactory()
                    ->getConverterForPHPValue($value)
                    ->output($value);
            }
        }

        $result = @pg_execute($this->connection->getResource(), $this->queryId, $stringParams);
        if (!$result) {
            throw new exceptions\InvalidQueryException(pg_last_error($this->connection->getResource()));
        }

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

            case PGSQL_COMMAND_OK:
                $count = pg_affected_rows($result);
                pg_free_result($result);
                return $count;

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