laminas/laminas-db

`Laminas\Db\Adapter\Driver\Pdo\Result#rewind()` can cause data loss by always reading row from database

Grundik opened this issue · 3 comments

Bug Report

Q A
Version(s) any since at least 2.0.0

Summary

Laminas\Db\Adapter\Driver\Pdo\Result->rewind() always reading one row from the database, even if its already read. That could lead to data loss, if ->rewind() called multiple times somehow.

Current behavior

Laminas\Db\Adapter\Driver\Pdo\Result->rewind() unconditionally reading one row:

        $this->currentData = $this->resource->fetch(\PDO::FETCH_ASSOC);
        $this->currentComplete = true;
        $this->position = 0;

(see https://github.com/laminas/laminas-db/blob/2.13.x/src/Adapter/Driver/Pdo/Result.php#L196)

How to reproduce

// make any query to database, resulting $result object
$result->rewind();
$result->rewind();
$data = $result->current(); // that would contain second readed row (if any). First one is lost.
$position = $result->key(); // that would return 0, not 1 as it is in fact

Expected behavior

Calling ->rewind() multiple times should not cause data loss. Method should make use of $this->currentComplete flag, and not fetch data if that already done, something like:

        if (!$this->currentComplete) {
            $this->currentData = $this->resource->fetch(\PDO::FETCH_ASSOC);
            $this->currentComplete = true;
        }
        $this->position = 0;

Thanks for reporting this, and for looking into the source code for the cause. I'll write a reproduction test case and then fix. I've got work-related time constraints, but I'll get to it as soon as I can.

Suggested fix in #273

Handled in #273