amphp / mysql

An async MySQL client for PHP, optimizing database interactions with efficient non-blocking capabilities. Perfect for responsive, high-performance applications.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

"Call to a member function updateState() on null" while traversing result set

Sevavietl opened this issue · comments

First of all, thank you for a great library.

In Amp\Mysql\Internal\Processor->successfulResultsetFetch() method, there can be a case where $this->result is null, but a method is executed on it:

private function successfulResultsetFetch() {
    $deferred = &$this->result->next;
    if ($this->connInfo->statusFlags & StatusFlags::SERVER_MORE_RESULTS_EXISTS) {
        $this->parseCallback = [$this, "handleQuery"];
        $this->addDeferred($deferred ?: $deferred = new Deferred);
    } else {
        if (!$deferred) {
            $deferred = new Deferred;
        }
        $deferred->resolve();
        $this->parseCallback = null;
        $this->query = null;
        $this->result = null;
        $this->ready();
    }
    $this->result->updateState(ResultProxy::ROWS_FETCHED);
}

In Amp\Mysql\Internal\Processor->prepareFields() there is a similar situation, but $this->result is stored in the temporary variable. When I use this approach in the situtaion above, the code goes fine, until $db->close(): "Connection went away... unable to fulfil this deferred ... It's unknown whether the query was executed..." (somehow there are still some elements in the $this->deferreds array during closing).

By the way I do not know why, but the script fails silently, and the only way I was able to see exception is to alter Amp\Internal\Placeholder:

/**
 * @param \Throwable $reason Failure reason.
 */
private function fail(\Throwable $reason) {
    var_dump($reason->getMessage());
    var_dump($reason->getTraceAsString());

    $this->resolve(new Failure($reason));
}

Thank you in advance.

@bwoebi, thank you for the fix.

But what about "Connection went away... unable to fulfil this deferred ... It's unknown whether the query was executed..."? Is this expected behavior?

This should just happen, if you force a $db->close() while some queries are still underway.
Does that always happen?

If I execute scripts from examples folder, everyone ends with this exception (if Amp\Internal\Placeholder edited to var_dump exception message).

It is failing the Deferred returned by Internal\Processor::sendClose() whose result is always ignored and not returned to userspace.

mysql/src/Connection.php

Lines 73 to 75 in f3e1f15

$processor->sendClose()->onResolve(static function () use ($processor) {
$processor->close();
});

It doesn't matter at all, though I agree, this could be solved a little more elegantly internally.

I've just committed ab1062a - this should remove all confusion you had ;-)

@bwoebi, thank you for the quick fixes.