public function fetchAll(?int $mode = null, $keyColumn = null, bool $forceArray = false, bool $group = false)
    {
        if (null !== $mode) {
            $oldMode = $this->mode;
            $this->setMode($mode);
        }
        if (null !== $keyColumn) {
            if ($this->numFields < 2) {
                throw new exceptions\InvalidArgumentException(
                    __METHOD__ . ': at least two columns needed for associative array result'
                );
            }
            $this->checkFieldIndex($keyColumn);
            if (PGSQL_ASSOC === $this->mode && ctype_digit((string)$keyColumn)) {
                $keyColumn = pg_field_name($this->resource, $keyColumn);
            } elseif (PGSQL_NUM === $this->mode && !ctype_digit((string)$keyColumn)) {
                $keyColumn = $this->namesHash[$keyColumn];
            }
        }
        $killArray = (!$forceArray && 2 === $this->numFields);

        $result = [];

        for ($i = 0; $i < $this->numRows; $i++) {
            $row = $this->read($i);
            if (null === $keyColumn) {
                $result[] = $row;

            } else {
                if (PGSQL_ASSOC === $this->mode) {
                    $key = $row[$keyColumn];
                    unset($row[$keyColumn]);
                } else {
                    list($key) = array_splice($row, $keyColumn, 1, []);
                }
                if ($killArray) {
                    $row = reset($row);
                }
                if ($group) {
                    $result[$key][] = $row;
                } else {
                    $result[$key] = $row;
                }
            }
        }

        if (isset($oldMode)) {
            $this->setMode($oldMode);
        }

        return $result;
    }