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