1
0
mirror of https://github.com/danog/postgres.git synced 2024-12-03 09:57:48 +01:00
postgres/test/AbstractLinkTest.php

686 lines
19 KiB
PHP
Raw Normal View History

<?php
2016-09-14 16:27:39 +02:00
namespace Amp\Postgres\Test;
use Amp\Delayed;
2017-05-26 17:47:44 +02:00
use Amp\Loop;
2019-09-27 05:41:47 +02:00
use Amp\PHPUnit\AsyncTestCase;
2020-08-28 19:26:11 +02:00
use Amp\Pipeline;
2017-11-06 01:12:12 +01:00
use Amp\Postgres\Link;
use Amp\Postgres\Listener;
use Amp\Postgres\QueryExecutionError;
use Amp\Postgres\Transaction;
2018-07-01 19:33:12 +02:00
use Amp\Sql\QueryError;
2020-05-23 00:53:14 +02:00
use Amp\Sql\Result;
2018-07-01 19:33:12 +02:00
use Amp\Sql\Statement;
use Amp\Sql\Transaction as SqlTransaction;
2018-07-03 01:45:09 +02:00
use Amp\Sql\TransactionError;
2020-10-11 18:49:15 +02:00
use function Amp\async;
use function Amp\asyncCallable;
use function Amp\await;
2016-09-14 16:27:39 +02:00
2019-09-27 05:41:47 +02:00
abstract class AbstractLinkTest extends AsyncTestCase
2018-07-01 19:33:12 +02:00
{
2020-10-11 18:49:15 +02:00
protected Link $link;
2016-09-14 16:27:39 +02:00
/**
* @return array Start test data for database.
*/
2020-02-06 23:34:49 +01:00
public function getData(): array
2018-07-01 19:33:12 +02:00
{
2016-09-14 16:27:39 +02:00
return [
['amphp', 'org'],
['github', 'com'],
['google', 'com'],
['php', 'net'],
];
}
2017-05-16 06:28:37 +02:00
2017-06-15 05:46:25 +02:00
/**
* @param string $connectionString
*
2020-10-11 18:49:15 +02:00
* @return Link Connection or Link object to be tested.
2017-06-15 05:46:25 +02:00
*/
2017-11-06 01:12:12 +01:00
abstract public function createLink(string $connectionString): Link;
2016-09-14 16:27:39 +02:00
2020-02-06 23:34:49 +01:00
public function setUp(): void
2018-07-01 19:33:12 +02:00
{
2019-09-27 05:41:47 +02:00
parent::setUp();
2020-10-11 18:49:15 +02:00
$this->link = $this->createLink('host=localhost user=postgres');
}
2020-10-11 18:49:15 +02:00
public function testQueryWithTupleResult()
2018-07-01 19:33:12 +02:00
{
2020-10-11 18:49:15 +02:00
$result = $this->link->query("SELECT * FROM test");
2017-05-16 06:28:37 +02:00
2019-09-27 05:41:47 +02:00
$data = $this->getData();
2016-09-14 16:27:39 +02:00
2020-10-11 18:49:15 +02:00
for ($i = 0; $row = $result->continue(); ++$i) {
2020-05-21 22:44:56 +02:00
$this->assertSame($data[$i][0], $row['domain']);
$this->assertSame($data[$i][1], $row['tld']);
}
2020-10-11 18:49:15 +02:00
$this->assertNull($result->getNextResult());
2020-05-21 22:44:56 +02:00
}
2020-10-11 18:49:15 +02:00
public function testMultipleQueryWithTupleResult()
2020-05-21 22:44:56 +02:00
{
2020-10-11 18:49:15 +02:00
$result = $this->link->query("SELECT * FROM test; SELECT * FROM test");
2020-05-23 00:53:14 +02:00
$data = $this->getData();
2020-10-11 18:49:15 +02:00
for ($i = 0; $row = $result->continue(); ++$i) {
2020-05-23 00:53:14 +02:00
$this->assertSame($data[$i][0], $row['domain']);
$this->assertSame($data[$i][1], $row['tld']);
}
2020-10-11 18:49:15 +02:00
$result = $result->getNextResult();
2020-05-23 00:53:14 +02:00
$this->assertInstanceOf(Result::class, $result);
2020-10-11 18:49:15 +02:00
for ($i = 0; $row = $result->continue(); ++$i) {
2020-05-23 00:53:14 +02:00
$this->assertSame($data[$i][0], $row['domain']);
$this->assertSame($data[$i][1], $row['tld']);
}
2020-10-11 18:49:15 +02:00
$this->assertNull($result->getNextResult());
2020-05-23 00:53:14 +02:00
}
2020-10-11 18:49:15 +02:00
public function testMultipleQueryWithCommandResultFirst()
2020-05-23 00:53:14 +02:00
{
2020-10-11 18:49:15 +02:00
$result = $this->link->query("INSERT INTO test (domain, tld) VALUES ('gitlab', 'com'); SELECT * FROM test");
2020-05-23 00:53:14 +02:00
2020-10-11 18:49:15 +02:00
$this->assertNull($result->continue());
2020-05-21 22:44:56 +02:00
2020-05-23 00:53:14 +02:00
$this->assertSame(1, $result->getRowCount());
2020-10-11 18:49:15 +02:00
$result = $result->getNextResult();
2020-05-23 00:53:14 +02:00
$this->assertInstanceOf(Result::class, $result);
2020-05-21 22:44:56 +02:00
$data = $this->getData();
2020-05-23 00:53:14 +02:00
$data[] = ['gitlab', 'com']; // Add inserted row to expected data.
2020-05-21 22:44:56 +02:00
2020-10-11 18:49:15 +02:00
for ($i = 0; $row = $result->continue(); ++$i) {
2020-05-21 22:44:56 +02:00
$this->assertSame($data[$i][0], $row['domain']);
$this->assertSame($data[$i][1], $row['tld']);
}
2020-10-11 18:49:15 +02:00
$this->assertNull($result->getNextResult());
2020-05-23 00:53:14 +02:00
}
2020-05-21 22:44:56 +02:00
2020-10-11 18:49:15 +02:00
public function testMultipleQueryWithCommandResultSecond()
2020-05-23 00:53:14 +02:00
{
2020-10-11 18:49:15 +02:00
$result = $this->link->query("SELECT * FROM test; INSERT INTO test (domain, tld) VALUES ('gitlab', 'com')");
2020-05-23 00:53:14 +02:00
$data = $this->getData();
2020-05-21 22:44:56 +02:00
2020-10-11 18:49:15 +02:00
for ($i = 0; $row = $result->continue(); ++$i) {
2019-09-27 05:41:47 +02:00
$this->assertSame($data[$i][0], $row['domain']);
$this->assertSame($data[$i][1], $row['tld']);
}
2020-05-23 00:53:14 +02:00
2020-10-11 18:49:15 +02:00
$result = $result->getNextResult();
2020-05-23 00:53:14 +02:00
2020-10-11 18:49:15 +02:00
$this->assertNull($result->continue());
2020-05-23 00:53:14 +02:00
$this->assertSame(1, $result->getRowCount());
2020-10-11 18:49:15 +02:00
$this->assertNull($result->getNextResult());
2016-09-14 16:27:39 +02:00
}
2020-10-11 18:49:15 +02:00
public function testQueryWithUnconsumedTupleResult()
2018-07-01 19:33:12 +02:00
{
2020-10-11 18:49:15 +02:00
$result = $this->link->query("SELECT * FROM test");
2020-05-23 00:53:14 +02:00
$this->assertInstanceOf(Result::class, $result);
2019-09-27 05:41:47 +02:00
unset($result); // Force destruction of result object.
2020-10-11 18:49:15 +02:00
$result = $this->link->query("SELECT * FROM test");
2019-09-27 05:41:47 +02:00
$data = $this->getData();
2020-10-11 18:49:15 +02:00
for ($i = 0; $row = $result->continue(); ++$i) {
2019-09-27 05:41:47 +02:00
$this->assertSame($data[$i][0], $row['domain']);
$this->assertSame($data[$i][1], $row['tld']);
}
}
2020-10-11 18:49:15 +02:00
public function testMultipleQueries()
2020-05-23 00:53:14 +02:00
{
2020-10-11 18:49:15 +02:00
$result = $this->link->query("SELECT * FROM test; INSERT INTO test (domain, tld) VALUES ('gitlab', 'com'); SELECT * FROM test");
2020-05-23 00:53:14 +02:00
$this->assertInstanceOf(Result::class, $result);
$data = $this->getData();
2020-10-11 18:49:15 +02:00
for ($i = 0; $row = $result->continue(); ++$i) {
2020-05-23 00:53:14 +02:00
$this->assertSame($data[$i][0], $row['domain']);
$this->assertSame($data[$i][1], $row['tld']);
}
2020-10-11 18:49:15 +02:00
$result = $result->getNextResult();
2020-05-23 00:53:14 +02:00
2020-10-11 18:49:15 +02:00
$this->assertNull($result->continue());
2020-05-23 00:53:14 +02:00
$this->assertSame(1, $result->getRowCount());
2020-10-11 18:49:15 +02:00
$result = $result->getNextResult();
2020-05-23 00:53:14 +02:00
$this->assertInstanceOf(Result::class, $result);
$data = $this->getData();
$data[] = ['gitlab', 'com']; // Add inserted row to expected data.
2020-10-11 18:49:15 +02:00
for ($i = 0; $row = $result->continue(); ++$i) {
2020-05-23 00:53:14 +02:00
$this->assertSame($data[$i][0], $row['domain']);
$this->assertSame($data[$i][1], $row['tld']);
}
2020-10-11 18:49:15 +02:00
$this->assertNull($result->getNextResult());
2020-05-23 00:53:14 +02:00
2020-10-11 18:49:15 +02:00
$this->assertNull($result->getNextResult());
2020-05-23 00:53:14 +02:00
}
2020-10-11 18:49:15 +02:00
public function testQueryWithCommandResult()
2018-07-01 19:33:12 +02:00
{
2020-10-11 18:49:15 +02:00
$result = $this->link->query("INSERT INTO test VALUES ('canon', 'jp')");
2016-09-14 16:27:39 +02:00
2020-05-23 00:53:14 +02:00
$this->assertInstanceOf(Result::class, $result);
$this->assertSame(1, $result->getRowCount());
2016-09-14 16:27:39 +02:00
}
2020-10-11 18:49:15 +02:00
public function testQueryWithEmptyQuery()
2018-07-01 19:33:12 +02:00
{
2020-02-06 23:34:49 +01:00
$this->expectException(QueryError::class);
2020-10-11 18:49:15 +02:00
$this->link->query('');
2016-09-14 16:27:39 +02:00
}
2020-10-11 18:49:15 +02:00
public function testQueryWithSyntaxError()
2018-07-01 19:33:12 +02:00
{
2020-05-23 00:53:14 +02:00
/** @var Result $result */
2019-09-27 05:41:47 +02:00
try {
2020-10-11 18:49:15 +02:00
$result = $this->link->query("SELECT & FROM test");
2019-09-27 05:41:47 +02:00
$this->fail(\sprintf("An instance of %s was expected to be thrown", QueryExecutionError::class));
} catch (QueryExecutionError $exception) {
$diagnostics = $exception->getDiagnostics();
$this->assertArrayHasKey("sqlstate", $diagnostics);
}
2016-09-14 16:27:39 +02:00
}
2020-10-11 18:49:15 +02:00
public function testPrepare()
2018-07-01 19:33:12 +02:00
{
2019-09-27 05:41:47 +02:00
$query = "SELECT * FROM test WHERE domain=\$1";
2016-09-14 16:27:39 +02:00
2019-09-27 05:41:47 +02:00
/** @var Statement $statement */
2020-10-11 18:49:15 +02:00
$statement = $this->link->prepare($query);
2016-09-14 16:27:39 +02:00
2019-09-27 05:41:47 +02:00
$this->assertSame($query, $statement->getQuery());
2016-09-14 16:27:39 +02:00
2019-09-27 05:41:47 +02:00
$data = $this->getData()[0];
2016-09-14 16:27:39 +02:00
2020-10-11 18:49:15 +02:00
$result = $statement->execute([$data[0]]);
2017-05-16 06:14:02 +02:00
2020-10-11 18:49:15 +02:00
while ($row = $result->continue()) {
2019-09-27 05:41:47 +02:00
$this->assertSame($data[0], $row['domain']);
$this->assertSame($data[1], $row['tld']);
}
2016-09-14 16:27:39 +02:00
}
/**
* @depends testPrepare
*/
2020-10-11 18:49:15 +02:00
public function testPrepareWithNamedParams()
2018-07-01 19:33:12 +02:00
{
2019-09-27 05:41:47 +02:00
$query = "SELECT * FROM test WHERE domain=:domain AND tld=:tld";
2020-10-11 18:49:15 +02:00
$statement = $this->link->prepare($query);
2019-09-27 05:41:47 +02:00
$data = $this->getData()[0];
2019-09-27 05:41:47 +02:00
$this->assertSame($query, $statement->getQuery());
2020-10-11 18:49:15 +02:00
$result = $statement->execute(['domain' => $data[0], 'tld' => $data[1]]);
2020-10-11 18:49:15 +02:00
while ($row = $result->continue()) {
2019-09-27 05:41:47 +02:00
$this->assertSame($data[0], $row['domain']);
$this->assertSame($data[1], $row['tld']);
}
}
/**
* @depends testPrepare
*/
2020-10-11 18:49:15 +02:00
public function testPrepareWithUnnamedParams()
2018-07-01 19:33:12 +02:00
{
2019-09-27 05:41:47 +02:00
$query = "SELECT * FROM test WHERE domain=? AND tld=?";
2020-10-11 18:49:15 +02:00
$statement = $this->link->prepare($query);
2019-09-27 05:41:47 +02:00
$data = $this->getData()[0];
2019-09-27 05:41:47 +02:00
$this->assertSame($query, $statement->getQuery());
2020-10-11 18:49:15 +02:00
$result = $statement->execute([$data[0], $data[1]]);
2020-10-11 18:49:15 +02:00
while ($row = $result->continue()) {
2019-09-27 05:41:47 +02:00
$this->assertSame($data[0], $row['domain']);
$this->assertSame($data[1], $row['tld']);
}
}
/**
* @depends testPrepare
*/
2020-10-11 18:49:15 +02:00
public function testPrepareWithNamedParamsWithDataAppearingAsNamedParam()
2018-07-01 19:33:12 +02:00
{
2019-09-27 05:41:47 +02:00
$query = "SELECT * FROM test WHERE domain=:domain OR domain=':domain'";
2020-10-11 18:49:15 +02:00
$statement = $this->link->prepare($query);
2019-09-27 05:41:47 +02:00
$data = $this->getData()[0];
2019-09-27 05:41:47 +02:00
$this->assertSame($query, $statement->getQuery());
2020-10-11 18:49:15 +02:00
$result = $statement->execute(['domain' => $data[0]]);
2020-05-23 00:53:14 +02:00
$this->assertInstanceOf(Result::class, $result);
2020-10-11 18:49:15 +02:00
while ($row = $result->continue()) {
2019-09-27 05:41:47 +02:00
$this->assertSame($data[0], $row['domain']);
$this->assertSame($data[1], $row['tld']);
}
}
/**
* @depends testPrepare
*/
2020-10-11 18:49:15 +02:00
public function testPrepareInvalidQuery()
2018-07-01 19:33:12 +02:00
{
2019-09-27 05:41:47 +02:00
$this->expectException(QueryExecutionError::class);
$this->expectExceptionMessage('column "invalid" does not exist');
2019-09-27 05:41:47 +02:00
$query = "SELECT * FROM test WHERE invalid=\$1";
2020-10-11 18:49:15 +02:00
$this->link->prepare($query);
}
/**
* @depends testPrepare
*/
2020-10-11 18:49:15 +02:00
public function testPrepareSameQuery()
2018-07-01 19:33:12 +02:00
{
2019-09-27 05:41:47 +02:00
$sql = "SELECT * FROM test WHERE domain=\$1";
2020-10-11 18:49:15 +02:00
$statement1 = $this->link->prepare($sql);
2020-10-11 18:49:15 +02:00
$statement2 = $this->link->prepare($sql);
2019-09-27 05:41:47 +02:00
$this->assertInstanceOf(Statement::class, $statement1);
$this->assertInstanceOf(Statement::class, $statement2);
2019-09-27 05:41:47 +02:00
unset($statement1);
2019-09-27 05:41:47 +02:00
$data = $this->getData()[0];
2020-10-11 18:49:15 +02:00
$result = $statement2->execute([$data[0]]);
2020-10-11 18:49:15 +02:00
while ($row = $result->continue()) {
2019-09-27 05:41:47 +02:00
$this->assertSame($data[0], $row['domain']);
$this->assertSame($data[1], $row['tld']);
}
}
/**
* @depends testPrepareSameQuery
*/
2020-10-11 18:49:15 +02:00
public function testSimultaneousPrepareSameQuery()
2018-07-01 19:33:12 +02:00
{
2019-09-27 05:41:47 +02:00
$sql = "SELECT * FROM test WHERE domain=\$1";
2020-10-11 18:49:15 +02:00
$statement1 = async(fn() => $this->link->prepare($sql));
$statement2 = async(fn() => $this->link->prepare($sql));
2020-10-11 18:49:15 +02:00
[$statement1, $statement2] = await([$statement1, $statement2]);
2019-09-27 05:41:47 +02:00
$data = $this->getData()[0];
2020-10-11 18:49:15 +02:00
$result = $statement1->execute([$data[0]]);
2020-10-11 18:49:15 +02:00
while ($row = $result->continue()) {
2019-09-27 05:41:47 +02:00
$this->assertSame($data[0], $row['domain']);
$this->assertSame($data[1], $row['tld']);
}
2019-09-27 05:41:47 +02:00
unset($statement1);
2020-10-11 18:49:15 +02:00
$result = $statement2->execute([$data[0]]);
2020-10-11 18:49:15 +02:00
while ($row = $result->continue()) {
2019-09-27 05:41:47 +02:00
$this->assertSame($data[0], $row['domain']);
$this->assertSame($data[1], $row['tld']);
}
}
2020-10-11 18:49:15 +02:00
public function testPrepareSimilarQueryReturnsDifferentStatements()
{
2020-10-11 18:49:15 +02:00
$statement1 = async(fn() => $this->link->prepare("SELECT * FROM test WHERE domain=\$1"));
2020-10-11 18:49:15 +02:00
$statement2 = async(fn() => $this->link->prepare("SELECT * FROM test WHERE domain=:domain"));
2020-10-11 18:49:15 +02:00
[$statement1, $statement2] = await([$statement1, $statement2]);
2019-09-27 05:41:47 +02:00
$this->assertInstanceOf(Statement::class, $statement1);
$this->assertInstanceOf(Statement::class, $statement2);
2019-09-27 05:41:47 +02:00
$this->assertNotSame($statement1, $statement2);
2019-09-27 05:41:47 +02:00
$data = $this->getData()[0];
2019-09-27 05:41:47 +02:00
$results = [];
2020-10-11 18:49:15 +02:00
$results[] = Pipeline\toArray($statement1->execute([$data[0]]));
$results[] = Pipeline\toArray($statement2->execute(['domain' => $data[0]]));
2019-09-27 05:41:47 +02:00
foreach ($results as $result) {
2020-05-23 00:53:14 +02:00
/** @var Result $result */
2019-09-27 05:41:47 +02:00
foreach ($result as $row) {
$this->assertSame($data[0], $row['domain']);
$this->assertSame($data[1], $row['tld']);
}
2019-09-27 05:41:47 +02:00
}
}
2020-10-11 18:49:15 +02:00
public function testPrepareThenExecuteWithUnconsumedTupleResult()
2018-07-01 19:33:12 +02:00
{
2020-10-11 18:49:15 +02:00
$statement = $this->link->prepare("SELECT * FROM test");
2020-10-11 18:49:15 +02:00
$result = $statement->execute();
2019-09-27 05:41:47 +02:00
unset($result); // Force destruction of result object.
2020-10-11 18:49:15 +02:00
$result = $statement->execute();
2019-09-27 05:41:47 +02:00
$data = $this->getData();
2020-10-11 18:49:15 +02:00
for ($i = 0; $row = $result->continue(); ++$i) {
2019-09-27 05:41:47 +02:00
$this->assertSame($data[$i][0], $row['domain']);
$this->assertSame($data[$i][1], $row['tld']);
}
}
2020-10-11 18:49:15 +02:00
public function testExecute()
2018-07-01 19:33:12 +02:00
{
2019-09-27 05:41:47 +02:00
$data = $this->getData()[0];
2016-09-14 16:27:39 +02:00
2020-10-11 18:49:15 +02:00
$result = $this->link->execute("SELECT * FROM test WHERE domain=\$1", [$data[0]]);
2016-09-14 16:27:39 +02:00
2020-10-11 18:49:15 +02:00
while ($row = $result->continue()) {
2019-09-27 05:41:47 +02:00
$this->assertSame($data[0], $row['domain']);
$this->assertSame($data[1], $row['tld']);
}
2016-09-14 16:27:39 +02:00
}
2017-11-06 06:06:17 +01:00
/**
* @depends testExecute
*/
2020-10-11 18:49:15 +02:00
public function testExecuteWithNamedParams()
2018-07-01 19:33:12 +02:00
{
2019-09-27 05:41:47 +02:00
$data = $this->getData()[0];
2020-10-11 18:49:15 +02:00
$result = $this->link->execute(
2019-09-27 05:41:47 +02:00
"SELECT * FROM test WHERE domain=:domain",
['domain' => $data[0]]
);
2020-05-23 00:53:14 +02:00
$this->assertInstanceOf(Result::class, $result);
2020-10-11 18:49:15 +02:00
while ($row = $result->continue()) {
2019-09-27 05:41:47 +02:00
$this->assertSame($data[0], $row['domain']);
$this->assertSame($data[1], $row['tld']);
}
}
/**
* @depends testExecute
2017-11-06 06:06:17 +01:00
*/
2020-10-11 18:49:15 +02:00
public function testExecuteWithInvalidParams()
2018-07-01 19:33:12 +02:00
{
2019-09-27 05:41:47 +02:00
$this->expectException(\Error::class);
$this->expectExceptionMessage("Value for unnamed parameter at position 0 missing");
2020-10-11 18:49:15 +02:00
$this->link->execute("SELECT * FROM test WHERE domain=\$1");
2017-11-06 06:06:17 +01:00
}
/**
* @depends testExecute
*/
2020-10-11 18:49:15 +02:00
public function testExecuteWithInvalidNamedParams()
2018-07-01 19:33:12 +02:00
{
2019-09-27 05:41:47 +02:00
$this->expectException(\Error::class);
$this->expectExceptionMessage("Value for named parameter 'domain' missing");
2020-10-11 18:49:15 +02:00
$this->link->execute("SELECT * FROM test WHERE domain=:domain", ['tld' => 'com']);
}
2016-09-14 16:27:39 +02:00
/**
* @depends testQueryWithTupleResult
2016-09-14 16:27:39 +02:00
*/
2020-10-11 18:49:15 +02:00
public function testSimultaneousQuery()
2018-07-01 19:33:12 +02:00
{
2020-10-11 18:49:15 +02:00
$callback = asyncCallable(function ($value) {
$result = $this->link->query("SELECT {$value} as value");
if ($value) {
2020-10-11 18:49:15 +02:00
new Delayed(100);
}
2020-10-11 18:49:15 +02:00
while ($row = $result->continue()) {
$this->assertEquals($value, $row['value']);
}
});
2020-10-11 18:49:15 +02:00
await([$callback(0), $callback(1)]);
}
/**
* @depends testSimultaneousQuery
*/
2020-10-11 18:49:15 +02:00
public function testSimultaneousQueryWithOneFailing()
2018-07-01 19:33:12 +02:00
{
2020-10-11 18:49:15 +02:00
$callback = asyncCallable(function ($query) {
$result = $this->link->query($query);
$data = $this->getData();
2017-05-16 06:14:02 +02:00
2020-10-11 18:49:15 +02:00
for ($i = 0; $row = $result->continue(); ++$i) {
$this->assertSame($data[$i][0], $row['domain']);
$this->assertSame($data[$i][1], $row['tld']);
}
return $result;
});
2019-09-27 05:41:47 +02:00
$result = null;
try {
2019-09-27 05:41:47 +02:00
$successful = $callback("SELECT * FROM test");
$failing = $callback("SELECT & FROM test");
2020-10-11 18:49:15 +02:00
$result = await($successful);
await($failing);
} catch (QueryError $exception) {
2020-05-23 00:53:14 +02:00
$this->assertInstanceOf(Result::class, $result);
return;
}
$this->fail(\sprintf("Test did not throw an instance of %s", QueryError::class));
}
2020-10-11 18:49:15 +02:00
public function testSimultaneousQueryAndPrepare()
2018-07-01 19:33:12 +02:00
{
$promises = [];
2020-10-11 18:49:15 +02:00
$promises[] = async(function () {
$result = $this->link->query("SELECT * FROM test");
$data = $this->getData();
2020-10-11 18:49:15 +02:00
for ($i = 0; $row = $result->continue(); ++$i) {
$this->assertSame($data[$i][0], $row['domain']);
$this->assertSame($data[$i][1], $row['tld']);
}
2020-10-11 18:49:15 +02:00
});
2020-10-11 18:49:15 +02:00
$promises[] = async(function () {
$statement = ($this->link->prepare("SELECT * FROM test"));
2020-10-11 18:49:15 +02:00
$result = $statement->execute();
$data = $this->getData();
2020-10-11 18:49:15 +02:00
for ($i = 0; $row = $result->continue(); ++$i) {
$this->assertSame($data[$i][0], $row['domain']);
$this->assertSame($data[$i][1], $row['tld']);
}
2020-10-11 18:49:15 +02:00
});
2020-10-11 18:49:15 +02:00
await($promises);
}
2020-10-11 18:49:15 +02:00
public function testSimultaneousPrepareAndExecute()
2018-07-01 19:33:12 +02:00
{
2020-10-11 18:49:15 +02:00
$promises[] = async(function () {
$statement = $this->link->prepare("SELECT * FROM test");
2020-10-11 18:49:15 +02:00
$result = $statement->execute();
$data = $this->getData();
2020-10-11 18:49:15 +02:00
for ($i = 0; $row = $result->continue(); ++$i) {
$this->assertSame($data[$i][0], $row['domain']);
$this->assertSame($data[$i][1], $row['tld']);
}
2020-10-11 18:49:15 +02:00
});
2020-10-11 18:49:15 +02:00
$promises[] = async(function () {
$result = $this->link->execute("SELECT * FROM test");
$data = $this->getData();
2020-10-11 18:49:15 +02:00
for ($i = 0; $row = $result->continue(); ++$i) {
$this->assertSame($data[$i][0], $row['domain']);
$this->assertSame($data[$i][1], $row['tld']);
2016-09-14 16:27:39 +02:00
}
2020-10-11 18:49:15 +02:00
});
2017-05-16 06:14:02 +02:00
2020-10-11 18:49:15 +02:00
await($promises);
2016-09-14 16:27:39 +02:00
}
2020-10-11 18:49:15 +02:00
public function testTransaction()
2018-07-01 19:33:12 +02:00
{
2019-09-27 05:41:47 +02:00
$isolation = SqlTransaction::ISOLATION_COMMITTED;
2016-09-14 16:27:39 +02:00
2020-10-11 18:49:15 +02:00
$transaction = $this->link->beginTransaction($isolation);
2016-09-14 16:27:39 +02:00
2019-09-27 05:41:47 +02:00
$this->assertInstanceOf(Transaction::class, $transaction);
2016-09-14 16:27:39 +02:00
2019-09-27 05:41:47 +02:00
$data = $this->getData()[0];
2016-09-14 16:27:39 +02:00
2019-09-27 05:41:47 +02:00
$this->assertTrue($transaction->isAlive());
$this->assertTrue($transaction->isActive());
$this->assertSame($isolation, $transaction->getIsolationLevel());
2016-09-14 16:27:39 +02:00
2020-10-11 18:49:15 +02:00
$transaction->createSavepoint('test');
2016-09-14 16:27:39 +02:00
2020-10-11 18:49:15 +02:00
$statement = $transaction->prepare("SELECT * FROM test WHERE domain=:domain");
$result = $statement->execute(['domain' => $data[0]]);
2020-05-23 00:53:14 +02:00
$this->assertInstanceOf(Result::class, $result);
2019-09-27 05:41:47 +02:00
unset($result); // Force destruction of result object.
2016-09-14 16:27:39 +02:00
2020-10-11 18:49:15 +02:00
$result = $transaction->execute("SELECT * FROM test WHERE domain=\$1 FOR UPDATE", [$data[0]]);
2020-05-23 00:53:14 +02:00
$this->assertInstanceOf(Result::class, $result);
2016-09-14 16:27:39 +02:00
2019-09-27 05:41:47 +02:00
unset($result); // Force destruction of result object.
2016-09-14 16:27:39 +02:00
2020-10-11 18:49:15 +02:00
$transaction->rollbackTo('test');
2016-09-14 16:27:39 +02:00
2020-10-11 18:49:15 +02:00
$transaction->commit();
2019-09-27 05:41:47 +02:00
$this->assertFalse($transaction->isAlive());
$this->assertFalse($transaction->isActive());
try {
2020-10-11 18:49:15 +02:00
$result = $transaction->execute("SELECT * FROM test");
2019-09-27 05:41:47 +02:00
$this->fail('Query should fail after transaction commit');
} catch (TransactionError $exception) {
// Exception expected.
}
2016-09-14 16:27:39 +02:00
}
2017-05-16 06:14:02 +02:00
2020-10-11 18:49:15 +02:00
public function testListen()
2018-07-01 19:33:12 +02:00
{
2019-09-27 05:41:47 +02:00
$channel = "test";
2020-10-11 18:49:15 +02:00
$listener = $this->link->listen($channel);
2019-09-27 05:41:47 +02:00
$this->assertInstanceOf(Listener::class, $listener);
$this->assertSame($channel, $listener->getChannel());
2020-10-11 18:49:15 +02:00
Loop::delay(100, asyncCallable(function () use ($channel) {
$this->link->query(\sprintf("NOTIFY %s, '%s'", $channel, '0'));
$this->link->query(\sprintf("NOTIFY %s, '%s'", $channel, '1'));
}));
2019-09-27 05:41:47 +02:00
$count = 0;
2020-10-11 18:49:15 +02:00
Loop::delay(200, asyncCallable(function () use ($listener) {
2019-09-27 05:41:47 +02:00
$listener->unlisten();
2020-10-11 18:49:15 +02:00
}));
2019-09-27 05:41:47 +02:00
2020-10-11 18:49:15 +02:00
while ($notification = $listener->continue()) {
2020-05-21 22:44:56 +02:00
$this->assertSame($notification->payload, (string) $count++);
2019-09-27 05:41:47 +02:00
}
$this->assertSame(2, $count);
}
/**
* @depends testListen
*/
2020-10-11 18:49:15 +02:00
public function testNotify()
2018-07-01 19:33:12 +02:00
{
2019-09-27 05:41:47 +02:00
$channel = "test";
2020-10-11 18:49:15 +02:00
$listener = $this->link->listen($channel);
2020-10-11 18:49:15 +02:00
Loop::delay(100, asyncCallable(function () use ($channel) {
$this->link->notify($channel, '0');
$this->link->notify($channel, '1');
}));
2019-09-27 05:41:47 +02:00
$count = 0;
2020-10-11 18:49:15 +02:00
Loop::delay(200, asyncCallable(function () use ($listener) {
2019-09-27 05:41:47 +02:00
$listener->unlisten();
2020-10-11 18:49:15 +02:00
}));
2019-09-27 05:41:47 +02:00
2020-10-11 18:49:15 +02:00
while ($notification = $listener->continue()) {
2020-05-21 22:44:56 +02:00
$this->assertSame($notification->payload, (string) $count++);
2019-09-27 05:41:47 +02:00
}
$this->assertSame(2, $count);
}
/**
* @depends testListen
*/
2020-10-11 18:49:15 +02:00
public function testListenOnSameChannel()
2018-07-01 19:33:12 +02:00
{
2019-09-27 05:41:47 +02:00
$this->expectException(QueryError::class);
$this->expectExceptionMessage('Already listening on channel');
$channel = "test";
2020-10-11 18:49:15 +02:00
await([$this->link->listen($channel), $this->link->listen($channel)]);
}
2016-09-14 16:27:39 +02:00
}