amphp / postgres

Async Postgres client for PHP based on Amp.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Transactions won't work if \pg_get_result returns multiple results

roquie opened this issue · comments

commented

Code to reproduce:

use Amp\Postgres;

Amp\Loop::run(function () {
    $config = Postgres\ConnectionConfig::fromString('host=localhost user=postgres');

    $pool = Postgres\pool($config);

    yield $pool->query('DROP TABLE IF EXISTS test');
    yield $pool->query('DROP TABLE IF EXISTS test2');

    /** @var \Amp\Postgres\Transaction $transaction */
    $transaction = yield $pool->beginTransaction();

    yield $transaction->query('
        CREATE TABLE test (domain VARCHAR(63), tld VARCHAR(63), PRIMARY KEY (domain, tld));
        CREATE TABLE test2 (domain VARCHAR(63), tld VARCHAR(63), PRIMARY KEY (domain, tld));
    ');

    yield $transaction->commit();
});

It fails with reason: Amp\Sql\FailureException: another command is already in progress

It happens because async version of \pg_send_query() can be accept sql queries with ; delimiter:
https://www.php.net/manual/en/function.pg-send-query.php
https://www.php.net/manual/en/function.pg-get-result.php

Unlike pg_query(), it can send multiple queries at once to PostgreSQL and get the results one by one using pg_get_result().

То fix this bug library should be to call \pg_get_result until it returns false.
https://github.com/amphp/postgres/blob/master/src/PgSqlHandle.php#L113

commented

I have no idea how to fix it with full backward compatibility. @trowski any comments?

P.S. this error will repeats with pecl pq extension also (but without any php-notices, just throws a TransactionError exception).

I did not know that pg_send_query supported sending multiple queries. I've obviously never tried to use this feature.

This could be fixed by using an approach similar to amphp/mysql. I think ResultSet could be extended in another interface to add a nextResultSet() method. v2 would merge the method into ResultSet, but for now an extra interface should be fine. Maybe there's a BC concern I'm not considering…

commented

I did not know that pg_send_query supported sending multiple queries.

Supports of sending multiple statement queries also should be available in the pq extension.

I've obviously never tried to use this feature.

Strangely. How to use this library with this bug in migrations? It uses all .sql file contents (with multiple queries) to ran. Real case: create a table, indexes and trigger in one migration file.

I think it should be part of standard functionality.

This could be fixed by using an approach similar to amphp/mysql

Good choice to use similar experience. With BC or not you can be interesting to be add this feature? I can try to help you as far as possible.

Strangely. How to use this library with this bug in migrations?

I've always imported .sql files on the command-line. I've never found a need to write code to do it.

Good choice to use similar experience. With BC or not you can be interesting to be add this feature? I can try to help you as far as possible.

I will put this on my long to-do list. It's not exactly a priority, but definitely something I'd do before a v2. I was considering doing a v2 if we merge amphp/amp#316 to switch ResultSet to implement Stream instead of Iterator.

commented

Okay. Good news :)

This has been implemented in the streams branch and will be included in v2.0.

commented

Yay! Thank you.

Note this got pushed to the Amp v3-compatible version, but that will be coming sometime this fall.

Multiple result sets from queries are now supported in the 2.x branch of this library. A few betas have been released, with a stable to be tagged in the coming months. I don't anticipate making any major API changes before a stable.

Thanks for pointing this out so it could be supported in the new version!