packages/ztd-query-core/tests/Unit/RewriteRefusalTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use ZtdQuery\Config\UnknownSchemaBehavior;
11use ZtdQuery\Config\UnsupportedSqlBehavior;
12use ZtdQuery\Config\ZtdConfig;
13use ZtdQuery\Connection\Exception\DatabaseException;
14use ZtdQuery\Exception\UnknownSchemaException;
15use ZtdQuery\Exception\UnsupportedSqlException;
16use ZtdQuery\Rewrite\QueryKind;
17use ZtdQuery\Rewrite\RewritePlan;
18use ZtdQuery\RewriteRefusal;
19
20#[CoversClass(RewriteRefusal::class)]
21#[UsesClass(ZtdConfig::class)]
22#[UsesClass(RewritePlan::class)]
23#[UsesClass(UnsupportedSqlException::class)]
24#[UsesClass(UnknownSchemaException::class)]
25#[UsesClass(DatabaseException::class)]
26final class RewriteRefusalTest extends TestCase
27{
28    public function testForUnsupportedRaisesWhereTheCallerAskedToBeTold(): void
29    {
30        $refusals = new RewriteRefusal(new ZtdConfig(unsupportedBehavior: UnsupportedSqlBehavior::Exception));
31
32        $this->expectException(DatabaseException::class);
33
34        $refusals->forUnsupported(new UnsupportedSqlException('SELECT 1', 'why'), 'SELECT 1');
35    }
36
37    public function testForUnsupportedAnswersAPlanThatDoesNothingWhereTheCallerAllowsThat(): void
38    {
39        $refusals = new RewriteRefusal(new ZtdConfig(unsupportedBehavior: UnsupportedSqlBehavior::Ignore));
40
41        $plan = $refusals->forUnsupported(new UnsupportedSqlException('SELECT 1', 'why'), 'SELECT 1');
42
43        self::assertSame([QueryKind::SKIPPED, 'SELECT 1'], [$plan->kind(), $plan->sql()]);
44    }
45
46    public function testForUnsupportedSaysSomethingWhereTheCallerAskedToBeNoticed(): void
47    {
48        $refusals = new RewriteRefusal(new ZtdConfig(unsupportedBehavior: UnsupportedSqlBehavior::Notice));
49        $said = null;
50        set_error_handler(static function (int $level, string $message) use (&$said): bool {
51            $said = $message;
52
53            return true;
54        }, E_USER_NOTICE);
55
56        try {
57            $refusals->forUnsupported(new UnsupportedSqlException('SELECT 1', 'why'), 'SELECT 1');
58        } finally {
59            restore_error_handler();
60        }
61
62        self::assertSame('[ZTD Notice] Unsupported SQL ignored: SELECT 1', $said);
63    }
64
65    public function testForUnknownSchemaRaisesWhereTheCallerAskedToBeTold(): void
66    {
67        $refusals = new RewriteRefusal(new ZtdConfig(unknownSchemaBehavior: UnknownSchemaBehavior::Exception));
68
69        $this->expectException(DatabaseException::class);
70
71        $refusals->forUnknownSchema(new UnknownSchemaException('SELECT 1', 't'), 'SELECT 1', 'SELECT 1 WHERE 0');
72    }
73
74    public function testForUnknownSchemaLetsTheStatementThroughWhereTheCallerAsksForThat(): void
75    {
76        $refusals = new RewriteRefusal(new ZtdConfig(unknownSchemaBehavior: UnknownSchemaBehavior::Passthrough));
77
78        $plan = $refusals->forUnknownSchema(new UnknownSchemaException('SELECT 1', 't'), 'SELECT 1', 'SELECT 1 WHERE 0');
79
80        self::assertSame([QueryKind::READ, 'SELECT 1'], [$plan->kind(), $plan->sql()]);
81    }
82
83    public function testForUnknownSchemaReadsNothingBackWhereTheCallerAsksForThat(): void
84    {
85        $refusals = new RewriteRefusal(new ZtdConfig(unknownSchemaBehavior: UnknownSchemaBehavior::EmptyResult));
86
87        $plan = $refusals->forUnknownSchema(new UnknownSchemaException('SELECT 1', 't'), 'SELECT 1', 'SELECT 1 WHERE 0');
88
89        self::assertSame([QueryKind::READ, 'SELECT 1 WHERE 0'], [$plan->kind(), $plan->sql()]);
90    }
91
92    public function testForUnknownSchemaSaysSomethingWhereTheCallerAskedToBeNoticed(): void
93    {
94        $refusals = new RewriteRefusal(new ZtdConfig(unknownSchemaBehavior: UnknownSchemaBehavior::Notice));
95        $said = null;
96        set_error_handler(static function (int $level, string $message) use (&$said): bool {
97            $said = $message;
98
99            return true;
100        }, E_USER_NOTICE);
101
102        try {
103            $refusals->forUnknownSchema(new UnknownSchemaException('SELECT 1', 't'), 'SELECT 1', 'SELECT 1 WHERE 0');
104        } finally {
105            restore_error_handler();
106        }
107
108        self::assertSame('[ZTD Notice] Unknown table referenced: t', $said);
109    }
110}
111