packages/ztd-query-mysql/tests/Unit/Sql/Transaction/MySqlTransactionStatementParserTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Sql\Transaction;
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\MySqlLexerProfile;
12use ZtdQuery\Platform\MySql\Sql\Transaction\MySqlTransactionStatementParser;
13use ZtdQuery\Shadow\ShadowStore;
14use ZtdQuery\Shadow\ShadowTransactions;
15
16#[CoversClass(MySqlTransactionStatementParser::class)]
17#[UsesClass(MySqlLexerProfile::class)]
18#[CoversClass(\ZtdQuery\Platform\MySql\Sql\Transaction\TokenReader::class)]
19final class MySqlTransactionStatementParserTest extends TestCase
20{
21 #[DataProvider('providerMySqlTransactionForms')]
22 public function testParsesMySqlTransactionForms(string $sql): void
23 {
24 self::assertNotNull((new MySqlTransactionStatementParser())->parse($sql));
25 }
26
27 /**
28
29 * @return array<string, array{string}>
30
31 */
32 public static function providerMySqlTransactionForms(): array
33 {
34 return [
35 'begin' => ['BEGIN;'],
36 'begin work' => ['BEGIN WORK'],
37 'start' => ['START TRANSACTION'],
38 'commit' => ['COMMIT'],
39 'commit work' => ['COMMIT WORK'],
40 'rollback' => ['ROLLBACK'],
41 'rollback work' => ['ROLLBACK WORK'],
42 'savepoint' => ['SAVEPOINT `a``b`'],
43 'rollback to' => ['ROLLBACK TO `a``b`'],
44 'rollback to savepoint' => ['ROLLBACK TO SAVEPOINT point'],
45 'release' => ['RELEASE SAVEPOINT point'],
46 ];
47 }
48
49 public function testRejectsNonMySqlAndMalformedForms(): void
50 {
51 $parser = new MySqlTransactionStatementParser();
52
53 self::assertNull($parser->parse(''));
54 self::assertNull($parser->parse('BEGIN IMMEDIATE'));
55 self::assertNull($parser->parse('END TRANSACTION'));
56 self::assertNull($parser->parse('RELEASE point'));
57 self::assertNull($parser->parse('SAVEPOINT point extra'));
58 self::assertNull($parser->parse('SAVEPOINT `broken'));
59 }
60
61 public function testAppliesUnescapedMySqlSavepointName(): void
62 {
63 $store = new ShadowStore();
64 $store->set('items', [['id' => 1]]);
65 $transactions = new ShadowTransactions($store);
66 $transactions->begin();
67 $statement = (new MySqlTransactionStatementParser())->parse('SAVEPOINT `a``b`');
68 self::assertNotNull($statement);
69 $statement->apply($transactions);
70 $store->insert('items', [['id' => 2]]);
71
72 $transactions->rollBackTo('a`b');
73
74 self::assertSame([['id' => 1]], $store->get('items'));
75 }
76}
77