diff --git a/src/Scaffolding/PostgresReflector.php b/src/Scaffolding/PostgresReflector.php index 9496d410d816ccd4e7ecc42ac3fef9cfdfdf13d2..da2d552bc28382783960da100453d7c2b3c6ced9 100644 --- a/src/Scaffolding/PostgresReflector.php +++ b/src/Scaffolding/PostgresReflector.php @@ -6,6 +6,7 @@ namespace Grifart\Tables\Scaffolding; use Dibi\Connection; use Grifart\Tables\ColumnMetadata; +use Grifart\Tables\MissingPrimaryIndex; use function Functional\map; use function Functional\reindex; @@ -75,6 +76,10 @@ WHERE pg_index.indisprimary AND pg_namespace.nspname = %s AND pg_class.relname = SQL , $schema, $table)->setType('indkey', null)->fetchSingle(); + if ($rawPrimaryKeyColumnPositions === null) { + throw MissingPrimaryIndex::in($schema, $table); + } + $primaryKeyColumnPositions = \explode(' ', $rawPrimaryKeyColumnPositions); return reindex( map( diff --git a/src/exceptions.php b/src/exceptions.php index cab513bb3cd16e9ded21c6ce5be17436f8164b00..b209bea166059deed76cce8d4aa037e849cf68c0 100644 --- a/src/exceptions.php +++ b/src/exceptions.php @@ -5,6 +5,14 @@ namespace Grifart\Tables; abstract class UsageException extends \LogicException {} abstract class RuntimeException extends \RuntimeException {} +final class MissingPrimaryIndex extends UsageException +{ + public static function in(string $schema, string $table): self + { + return new self(\sprintf('Table "%s"."%s" must have a primary index. Provide one and try again.', $schema, $table)); + } +} + final class ProbablyBrokenPrimaryIndexImplementation extends UsageException { public function __construct(Table $table, int $affectedRows) { diff --git a/tests/Fixtures/.definition.missingPrimaryIndex.php b/tests/Fixtures/.definition.missingPrimaryIndex.php new file mode 100644 index 0000000000000000000000000000000000000000..b909be3cf3965a6eb5f7c98d66318d3501ede231 --- /dev/null +++ b/tests/Fixtures/.definition.missingPrimaryIndex.php @@ -0,0 +1,32 @@ +<?php + +declare(strict_types=1); + +namespace Grifart\Tables\Tests\Fixtures; + +use Dibi\Connection; +use Grifart\Tables\Database\Identifier; +use Grifart\Tables\Scaffolding\PostgresReflector; +use Grifart\Tables\Scaffolding\TablesDefinitions; +use Grifart\Tables\TypeResolver; +use Grifart\Tables\Types\TextType; + + +$connection = require __DIR__ . '/../createConnection.local.php'; +\assert($connection instanceof Connection); + +$reflector = new PostgresReflector($connection); +$typeResolver = (new TypeResolver($connection)); +$typeResolver->addResolutionByLocation(new Identifier('public', 'missingPrimaryIndex', 'whatever'), TextType::text()); +$tableDefinitions = new TablesDefinitions($reflector, $typeResolver); + +return [ + ...$tableDefinitions->for( + 'public', + 'missingPrimaryIndex', + MissingPrimaryIndexRow::class, + MissingPrimaryIndexModifications::class, + MissingPrimaryIndexTable::class, + MissingPrimaryIndexPrimaryKey::class, + ) +]; diff --git a/tests/Scaffolding/ScaffoldingTest.missingPrimaryIndex.phpt b/tests/Scaffolding/ScaffoldingTest.missingPrimaryIndex.phpt new file mode 100644 index 0000000000000000000000000000000000000000..b7ac41c9e7bad984dac8206f47809c5a62f93d29 --- /dev/null +++ b/tests/Scaffolding/ScaffoldingTest.missingPrimaryIndex.phpt @@ -0,0 +1,25 @@ +<?php declare(strict_types = 1); + +namespace Grifart\Tables\Tests\Scaffolding; + +use Grifart\ClassScaffolder\Definition\ClassDefinition; +use Grifart\ClassScaffolder\DefinitionFile; +use Grifart\ClassScaffolder\DefinitionResult; +use Grifart\ClassScaffolder\FileProcessor; +use Tester\Assert; +use function Grifart\Tables\Tests\connect; + + +require __DIR__ . '/../bootstrap.php'; + +connect(); + +$fileProcessor = new FileProcessor(); + +$results = $fileProcessor->processFile( + DefinitionFile::from(__DIR__ . '/../Fixtures/.definition.missingPrimaryIndex.php'), + static fn(ClassDefinition $definition) => DefinitionResult::success($definition), // won't be called but has to return something +); + +Assert::true( ! $results->isSuccessful()); +Assert::same('Table "public"."missingPrimaryIndex" must have a primary index. Provide one and try again.', $results->getError()->getMessage()); diff --git a/tests/initializeDatabase.php b/tests/initializeDatabase.php index 68d13a296139d9d19d2ce60fe559649d629c9fb4..f1094c2b8425a6c6f656010038a83daabdd5395a 100644 --- a/tests/initializeDatabase.php +++ b/tests/initializeDatabase.php @@ -33,3 +33,9 @@ CREATE TABLE IF NOT EXISTS public.package ( "previousVersions" public."packageVersion"[] NOT NULL ); SQL); + +$connection->nativeQuery(<<<SQL +CREATE TABLE IF NOT EXISTS public."missingPrimaryIndex" ( + whatever text NOT NULL +); +SQL);