diff --git a/.travis.yml b/.travis.yml index 01ca501..59adafc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,13 @@ matrix: - DEPENDENCIES="" - DRIVER="pdo_mysql" - DB=mysql_5.7 + - php: 7.1 + sudo: true + env: + - DEPENDENCIES="" + - DRIVER="pdo_mysql" + - DB=mysql_5.7 + - DB_ATTR_ERRMODE=2 # \PDO::ERRMODE_EXCEPTION - php: 7.1 sudo: true env: @@ -63,6 +70,17 @@ matrix: - DB=postgres_9.5 addons: postgresql: '9.5' + - php: 7.1 + dist: trusty + env: + - DEPENDENCIES="" + - EXECUTE_CS_CHECK=false + - TEST_COVERAGE=true + - DRIVER="pdo_pgsql" + - DB=postgres_9.5 + - DB_ATTR_ERRMODE=2 # \PDO::ERRMODE_EXCEPTION + addons: + postgresql: '9.5' - php: 7.1 dist: trusty env: @@ -70,7 +88,7 @@ matrix: - DRIVER="pdo_pgsql" - DB=postgres_9.5 addons: -postgresql: '9.5' + postgresql: '9.5' cache: directories: diff --git a/docker-compose-tests.yml b/docker-compose-tests.yml new file mode 100644 index 0000000..ddf38ec --- /dev/null +++ b/docker-compose-tests.yml @@ -0,0 +1,25 @@ +version: '2' +services: + composer: + image: prooph/composer:7.1 + volumes: + - .:/app + links: + - postgres:postgres + - mysql:mysql + + postgres: + image: postgres:alpine + ports: + - 5432:5432 + environment: + - POSTGRES_DB=snapshot_tests + + mysql: + image: mysql + ports: + - 3306:3306 + environment: + - MYSQL_ROOT_PASSWORD= + - MYSQL_ALLOW_EMPTY_PASSWORD=yes + - MYSQL_DATABASE=snapshot_tests diff --git a/phpunit.xml.pdo_mysql b/phpunit.xml.pdo_mysql index 4842cbd..61b8a35 100644 --- a/phpunit.xml.pdo_mysql +++ b/phpunit.xml.pdo_mysql @@ -1,15 +1,17 @@ - ./tests @@ -22,11 +24,13 @@ - - - - - - + + + + + + + + diff --git a/phpunit.xml.pdo_pgsql b/phpunit.xml.pdo_pgsql index ae34302..16defbe 100644 --- a/phpunit.xml.pdo_pgsql +++ b/phpunit.xml.pdo_pgsql @@ -1,15 +1,17 @@ - ./tests @@ -22,11 +24,13 @@ - - - - - - + + + + + + + + diff --git a/src/Exception/RuntimeException.php b/src/Exception/RuntimeException.php new file mode 100644 index 0000000..e15ee86 --- /dev/null +++ b/src/Exception/RuntimeException.php @@ -0,0 +1,29 @@ + + * (c) 2016-2017 Sascha-Oliver Prolic + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace Prooph\SnapshotStore\Pdo\Exception; + +use RuntimeException as PHPRuntimeException; + +class RuntimeException extends PHPRuntimeException +{ + public static function fromStatementErrorInfo(array $errorInfo): RuntimeException + { + return new self( + sprintf( + "Error %s. \nError-Info: %s", + $errorInfo[0], + $errorInfo[2] + ) + ); + } +} diff --git a/src/PdoSnapshotStore.php b/src/PdoSnapshotStore.php index d363c2c..e28a8ec 100644 --- a/src/PdoSnapshotStore.php +++ b/src/PdoSnapshotStore.php @@ -13,7 +13,9 @@ namespace Prooph\SnapshotStore\Pdo; use PDO; +use PDOException; use Prooph\SnapshotStore\CallbackSerializer; +use Prooph\SnapshotStore\Pdo\Exception\RuntimeException; use Prooph\SnapshotStore\Serializer; use Prooph\SnapshotStore\Snapshot; use Prooph\SnapshotStore\SnapshotStore; @@ -63,7 +65,15 @@ public function get(string $aggregateType, string $aggregateId): ?Snapshot EOT; $statement = $this->connection->prepare($query); - $statement->execute([$aggregateId]); + try { + $statement->execute([$aggregateId]); + } catch (PDOException $exception) { + // ignore and check error code + } + + if ($statement->errorCode() !== '00000') { + throw RuntimeException::fromStatementErrorInfo($statement->errorInfo()); + } $result = $statement->fetch(\PDO::FETCH_OBJ); @@ -129,8 +139,13 @@ public function save(Snapshot ...$snapshots): void $this->connection->beginTransaction(); - foreach ($statements as $statement) { - $statement->execute(); + try { + foreach ($statements as $statement) { + $statement->execute(); + } + } catch (PDOException $exception) { + $this->connection->rollBack(); + throw RuntimeException::fromStatementErrorInfo($statement->errorInfo()); } $this->connection->commit(); @@ -148,7 +163,16 @@ public function removeAll(string $aggregateType): void $this->connection->beginTransaction(); - $statement->execute([$aggregateType]); + try { + $statement->execute([$aggregateType]); + } catch (PDOException $exception) { + // ignore and check error code + } + + if ($statement->errorCode() !== '00000') { + $this->connection->rollBack(); + throw RuntimeException::fromStatementErrorInfo($statement->errorInfo()); + } $this->connection->commit(); } diff --git a/tests/PdoSnapshotStoreTest.php b/tests/PdoSnapshotStoreTest.php index 27a922b..1593967 100644 --- a/tests/PdoSnapshotStoreTest.php +++ b/tests/PdoSnapshotStoreTest.php @@ -151,7 +151,7 @@ public function it_uses_custom_snapshot_table_map() protected function setUp(): void { $this->connection = TestUtil::getConnection(); - + $this->connection->exec('DROP TABLE IF EXISTS snapshots'); switch (TestUtil::getDatabaseVendor()) { case 'pdo_mysql': $this->connection->exec(file_get_contents(__DIR__ . '/../scripts/mysql_snapshot_table.sql')); @@ -168,9 +168,9 @@ protected function setUp(): void protected function tearDown(): void { - $statement = $this->connection->prepare('TRUNCATE snapshots'); + $statement = $this->connection->prepare('DROP TABLE IF EXISTS snapshots'); $statement->execute(); - $statement = $this->connection->prepare('TRUNCATE bar'); + $statement = $this->connection->prepare('DROP TABLE IF EXISTS bar'); $statement->execute(); } diff --git a/tests/TestUtil.php b/tests/TestUtil.php index 06fa61c..861ee9e 100644 --- a/tests/TestUtil.php +++ b/tests/TestUtil.php @@ -41,7 +41,7 @@ public static function getConnection(): PDO $dsn .= 'dbname=' . $connectionParams['dbname'] . $separator; $dsn = rtrim($dsn); - return new PDO($dsn, $connectionParams['user'], $connectionParams['password']); + return new PDO($dsn, $connectionParams['user'], $connectionParams['password'], $connectionParams['options']); } public static function getDatabaseName(): string @@ -50,7 +50,7 @@ public static function getDatabaseName(): string throw new \RuntimeException('No connection params given'); } - return $GLOBALS['db_name']; + return getenv('db_name'); } public static function getDatabaseVendor(): string @@ -59,7 +59,7 @@ public static function getDatabaseVendor(): string throw new \RuntimeException('No connection params given'); } - return $GLOBALS['db_type']; + return getenv('db_type'); } public static function getConnectionParams(): array @@ -73,25 +73,28 @@ public static function getConnectionParams(): array private static function hasRequiredConnectionParams(): bool { + $env = getenv(); + return isset( - $GLOBALS['db_type'], - $GLOBALS['db_username'], - $GLOBALS['db_password'], - $GLOBALS['db_host'], - $GLOBALS['db_name'], - $GLOBALS['db_port'] + $env['db_type'], + $env['db_username'], + $env['db_password'], + $env['db_host'], + $env['db_name'], + $env['db_port'] ); } private static function getSpecifiedConnectionParams(): array { return [ - 'driver' => $GLOBALS['db_type'], - 'user' => $GLOBALS['db_username'], - 'password' => $GLOBALS['db_password'], - 'host' => $GLOBALS['db_host'], - 'dbname' => $GLOBALS['db_name'], - 'port' => $GLOBALS['db_port'], + 'driver' => getenv('db_type'), + 'user' => getenv('db_username'), + 'password' => getenv('db_password'), + 'host' => getenv('db_host'), + 'dbname' => getenv('db_name'), + 'port' => getenv('db_port'), + 'options' => [PDO::ATTR_ERRMODE => (int) getenv('DB_ATTR_ERRMODE')], ]; } }