1
0
mirror of https://github.com/danog/postgres.git synced 2024-11-29 20:19:10 +01:00

Fix resuing hashed name for similar queries

This commit is contained in:
Aaron Piotrowski 2019-03-29 10:39:32 -05:00
parent ccce08f5f2
commit cf43bc03ac
No known key found for this signature in database
GPG Key ID: ADD1EF783EDE9EEB
4 changed files with 28 additions and 10 deletions

View File

@ -366,7 +366,7 @@ final class PgSqlHandle implements Handle
$modifiedSql = Internal\parseNamedParams($sql, $names);
$name = Handle::STATEMENT_NAME_PREFIX . \sha1($modifiedSql);
$name = Handle::STATEMENT_NAME_PREFIX . \sha1($sql);
if (isset($this->statements[$name])) {
$storage = $this->statements[$name];

View File

@ -54,9 +54,7 @@ final class Pool extends ConnectionPool implements Link
$this->statements = $statements = new class($maxConnections) extends LRUCache implements \IteratorAggregate {
public function getIterator(): \Iterator
{
foreach ($this->data as $key => $data) {
yield $key => $data;
}
yield from $this->data;
}
};
@ -147,8 +145,10 @@ final class Pool extends ConnectionPool implements Link
}
return call(function () use ($sql) {
if ($this->statements->containsKey($sql)) {
$statement = $this->statements->get($sql);
$name = Handle::STATEMENT_NAME_PREFIX . \sha1($sql);
if ($this->statements->containsKey($name)) {
$statement = $this->statements->get($name);
if ($statement instanceof Promise) {
$statement = yield $statement; // Wait for prior request to resolve.
@ -162,17 +162,17 @@ final class Pool extends ConnectionPool implements Link
}
$promise = parent::prepare($sql);
$this->statements->put($sql, $promise); // Insert promise into queue so subsequent requests get promise.
$this->statements->put($name, $promise); // Insert promise into queue so subsequent requests get promise.
try {
$statement = yield $promise;
\assert($statement instanceof StatementPool);
} catch (\Throwable $exception) {
$this->statements->remove($sql);
$this->statements->remove($name);
throw $exception;
}
$this->statements->put($sql, $statement); // Replace promise in queue with statement object.
$this->statements->put($name, $statement); // Replace promise in queue with statement object.
return $statement;
});

View File

@ -387,7 +387,7 @@ final class PqHandle implements Handle
$modifiedSql = Internal\parseNamedParams($sql, $names);
$name = Handle::STATEMENT_NAME_PREFIX . \sha1($modifiedSql);
$name = Handle::STATEMENT_NAME_PREFIX . \sha1($sql);
if (isset($this->statements[$name])) {
$storage = $this->statements[$name];

View File

@ -346,6 +346,24 @@ abstract class AbstractLinkTest extends TestCase
});
}
public function testPrepareSimilarQueryReturnsDifferentStatements()
{
Loop::run(function () {
/** @var Statement $statement1 */
$statement1 = $this->connection->prepare("SELECT * FROM test WHERE domain=\$1");
/** @var Statement $statement2 */
$statement2 = $this->connection->prepare("SELECT * FROM test WHERE domain=:domain");
list($statement1, $statement2) = yield [$statement1, $statement2];
$this->assertInstanceOf(Statement::class, $statement1);
$this->assertInstanceOf(Statement::class, $statement2);
$this->assertNotSame($statement1, $statement2);
});
}
public function testPrepareThenExecuteWithUnconsumedTupleResult()
{
Loop::run(function () {