packages/sql-fixture/tests/Unit/Fixture/Generation/RelationProjectionTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Fixture\Generation;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\TestCase;
9use SqlFixture\Fixture\Generation\RelationProjection as Subject;
10use SqlFixture\Plan\FixturePlan;
11use SqlFixture\Plan\Relation;
12
13#[CoversClass(Subject::class)]
14#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Fixture\PlanSchemaException::class)]
15#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\ColumnRef::class)]
16#[\PHPUnit\Framework\Attributes\UsesClass(FixturePlan::class)]
17#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\PlanParser::class)]
18#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\PlanPrinter::class)]
19#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\PlanSyntaxException::class)]
20#[\PHPUnit\Framework\Attributes\UsesClass(Relation::class)]
21#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\RelationKind::class)]
22#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\RelationSide::class)]
23#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Schema\ColumnDefinition::class)]
24#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Schema\TableSchema::class)]
25#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\Parsing\PlanStatements::class)]
26#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\Parsing\RelationCursor::class)]
27#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\Parsing\RelationReader::class)]
28#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\PlanStructureException::class)]
29#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\Printing\PlanTables::class)]
30#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\Printing\RelationGroups::class)]
31#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\Printing\StatementPrinter::class)]
32#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\Validation\PlanValidation::class)]
33#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\Validation\TableName::class)]
34#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Fixture\Exception\GeneratedColumnReferenceException::class)]
35#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Fixture\Exception\MissingRelationValueException::class)]
36#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Fixture\Exception\UnknownPlanColumnException::class)]
37#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\Exception\EmptyPlanException::class)]
38#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\Exception\EmptyTableNameException::class)]
39#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\Exception\MissingEndpointColumnsException::class)]
40#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\Exception\InvalidTableNameException::class)]
41#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\Exception\UnbalancedBracketsException::class)]
42#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\Exception\UnexpectedPlanTokenException::class)]
43#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\Exception\UnsupportedManyToManyException::class)]
44#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\Exception\CompositeArityMismatchException::class)]
45#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\Exception\DuplicateColumnBindingException::class)]
46#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\Exception\CyclicDependencyException::class)]
47#[\PHPUnit\Framework\Attributes\UsesClass(\SqlFixture\Plan\Exception\UnboundedSelfReferenceException::class)]
48final class RelationProjectionTest extends TestCase
49{
50    public function testReferencedColumnsDeduplicatesParentKeys(): void
51    {
52        $plan = FixturePlan::from('a.id < b.a_id; a.id < c.a_id');
53        self::assertSame(['id'], (new Subject())->referencedColumns($plan, 'a'));
54        self::assertSame([], (new Subject())->referencedColumns($plan, 'b'));
55    }
56
57    public function testIsAlreadyLinkedRequiresEveryCompositeColumn(): void
58    {
59        $relation = Relation::oneToMany('a.(id, tenant)', 'b.(a_id, tenant)');
60        $projection = new Subject();
61        self::assertTrue($projection->isAlreadyLinked($relation, ['a_id' => 9, 'tenant' => 2]));
62        self::assertFalse($projection->isAlreadyLinked($relation, ['a_id' => 9]));
63    }
64
65    public function testProjectMapsCompositeKeysWithoutUnrelatedColumns(): void
66    {
67        $relation = Relation::oneToMany('a.(id, tenant)', 'b.(a_id, tenant)');
68        self::assertSame(['a_id' => 9, 'tenant' => 2], (new Subject())->project(['id' => 9, 'tenant' => 2, 'name' => 'A'], $relation));
69    }
70}
71