packages/ztd-query-mysql/tests/Unit/Sql/Dml/UpdateSourceExtractorTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Sql\Dml;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\DataProvider;
9use PHPUnit\Framework\Attributes\UsesClass;
10use PHPUnit\Framework\TestCase;
11use ZtdQuery\Platform\MySql\Sql\Dml\UpdateSourceExtractor;
12
13#[CoversClass(UpdateSourceExtractor::class)]
14#[UsesClass(\ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::class)]
15final class UpdateSourceExtractorTest extends TestCase
16{
17    #[DataProvider('providerSources')]
18    public function testExtract(string $sql, ?string $expected): void
19    {
20        self::assertSame($expected, (new UpdateSourceExtractor())->extract($sql));
21    }
22
23    /**
24     * @return iterable<string, array{string, string|null}>
25     */
26    public static function providerSources(): iterable
27    {
28        yield 'derived join' => [
29            'UPDATE summary s JOIN (SELECT category, COUNT(*) AS cnt FROM products GROUP BY category) p ON s.category = p.category SET s.item_count = p.cnt',
30            'summary s JOIN (SELECT category, COUNT(*) AS cnt FROM products GROUP BY category) p ON s.category = p.category',
31        ];
32        yield 'window expression and nested set token' => [
33            "UPDATE rankings r JOIN (SELECT player, DENSE_RANK() OVER (ORDER BY MAX(score) DESC) AS ranking, 'SET' AS marker FROM scores GROUP BY player) s ON r.player = s.player SET r.rank_pos = s.ranking",
34            "rankings r JOIN (SELECT player, DENSE_RANK() OVER (ORDER BY MAX(score) DESC) AS ranking, 'SET' AS marker FROM scores GROUP BY player) s ON r.player = s.player",
35        ];
36        yield 'modifiers and comments' => [
37            'UPDATE /* before */ LOW_PRIORITY /* middle */ IGNORE /* source */ users AS u SET u.active = 1',
38            'users AS u',
39        ];
40        yield 'quoted modifier name' => [
41            'UPDATE `ignore` SET value = 1',
42            '`ignore`',
43        ];
44        yield 'not update' => ['SELECT 1', null];
45        yield 'missing source' => ['UPDATE SET value = 1', null];
46    }
47}
48