amphp / postgres

Async Postgres client for PHP based on Amp.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Prepared statements

bputt opened this issue · comments

commented

I submitted an issue at crate/crate#6785 and they mentioned switching to the protocol level prepared statement functionality.

Are you not using the "protocol level prepared statement functionality" because of how this library asynchronously interacts with postgresql?

This library is really just a wrapper around two PHP extensions, ext/pgsql and pecl/pq. I know that in pecl/pq the prepare() method works by executing a standard PREPARE query, I suspect ext/pgsql does as well.

I will look into this further upstream and report back.

OK so I looked into this and actually both underlying extensions already use protocol-level prepares. There is no such thing as a protocol-level deallocation (at least, not in libpq):

although there is no libpq function for deleting a prepared statement, the SQL DEALLOCATE statement can be used for that purpose.

pecl/pq provides a function that wraps this statement for convenience only. This is done "manually" when using ext/pgsql.

Can you explain the problem you are having in the original crate issue? I'm not clear on what exactly was throwing an error? Is it that when amp/postgres tries to automatically deallocate the statement when it is destroyed, the remote server throws because it doesn't understand DEALLOCATE?

@bputt This library uses either ext-pgsql or pecl-pq, which as I understand use libpq to communicate with the Postgres server. Which backend are you using? As @DaveRandom pointed out, this library sends a DEALLOCATE query when using ext-pgsql, and it appears pecl-pq does essentially the same thing.

I too would like a bit more clarification on what "protocol level prepared statement functionality" means. I guess that would require implementing the protocol that libpq uses to communicate over the wire with the postgres server, something I'm not terribly interested in doing when libpq works so well. Additionally, that implementation would still send a DEALLOCATE query, because you're suppose to deallocate statements if the connection is to be left open.

If it interests you, you may be able to write a custom implementation of Handle and Connection by largely copy/pasting the existing implementation for an extension and modifying it how you see fit. I'm close to tagging v0.3, so you may want to wait until after that.

commented

The remote server (CrateDB) throws an error message stating that DEALLOCATE is not supported.

We are able to get data back from Crate, so we can still get around the exception. I'm just not sure how this will affect performance yet.

We're using the ext/pgsq lib. Should we try the pecl/pq?

For simplicity, $queries will contain multiple queries, but will only include one for this example

$queries = [
    [
        'key' => 'totalRows',
        'statement' => 'SELECT COUNT(*) as numRows FROM mytable WHERE x = ?',
        'where' => [
            'vals' => [ 'abc' ]
        ],
        'params' => []
    ]
];
use Amp\Loop;
use Amp\Postgres;

$returnData = [];

// This section below is in a try catch and will only throw an error if it doesn't refer to the deallocate function
$pool = Postgres\pool('my dsn string');

Loop::run(function() use ($queries, $pool, &$returnData) {
    $promises = [];
    $results = [];

    foreach ($queries as $query) {
        $key = $query['key'];
        $promises[$key] = yield $pool->prepare($query['statement'], $query['params']);
        $results[$key] = yield $promises[$key]->execute($query['where']['vals']);
    }

    foreach($results as $key => $result) {
        $returnData[$key] = [];

        while (yield $result->advance()) {
            $item = $result->getCurrent();
            $returnData[$key][] = $item;
        }
    }
});

Closing as this issue appears to have been resolved by crates implementing the DEALLOCATE statement.