packages/ztd-query-mysql/tests/Unit/Rewrite/Upsert/ExpressionBinderTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Rewrite\Upsert;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\TestCase;
9use ZtdQuery\Platform\MySql\Rewrite\Upsert\ExpressionBinder;
10
11#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\MySql\Sql\MySqlIdentifierQuoter::class)]
12#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::class)]
13#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\MySql\Rewrite\Upsert\QualifiedColumn::class)]
14#[CoversClass(ExpressionBinder::class)]
15final class ExpressionBinderTest extends TestCase
16{
17 public function testBindExpression(): void
18 {
19 $binder = new ExpressionBinder(new \ZtdQuery\Platform\MySql\Sql\MySqlIdentifierQuoter(), \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create());
20 self::assertSame('`__ztd_existing`.`score` + `__ztd_incoming`.`score` + `__ztd_incoming`.`score` + (SELECT score FROM t) + other.score', $binder->bindExpression('t.score + VALUES(score) + new.score + (SELECT score FROM t) + other.score', 't', ['score'], incomingNamespace: 'new'));
21 self::assertSame('ABS(`custom`.`score`)', $binder->bindExpression('ABS(score)', 't', ['score'], 'custom'));
22 }
23
24 public function testSubqueryTokenIndexes(): void
25 {
26 $binder = new ExpressionBinder(new \ZtdQuery\Platform\MySql\Sql\MySqlIdentifierQuoter(), \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create());
27 $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize('id + (SELECT score FROM t)', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens();
28 self::assertSame([3 => true, 4 => true, 5 => true, 6 => true], $binder->subqueryTokenIndexes($tokens));
29 }
30
31 public function testIdentifier(): void
32 {
33 $binder = new ExpressionBinder(new \ZtdQuery\Platform\MySql\Sql\MySqlIdentifierQuoter(), \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create());
34 $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize('`a``b` +', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens();
35 self::assertSame('a`b', $binder->identifier($tokens[0]));
36 self::assertSame('+', $binder->identifier($tokens[1]));
37 }
38
39 public function testBindingAt(): void
40 {
41 $binder = new ExpressionBinder(new \ZtdQuery\Platform\MySql\Sql\MySqlIdentifierQuoter(), \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create());
42 $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize('score + 1', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens();
43 self::assertSame(['offset' => 0, 'length' => 5, 'value' => '`old`.`score`'], $binder->bindingAt($tokens, 0, ['score' => true], [], 't', 'old'));
44 self::assertNull($binder->bindingAt($tokens, 0, [], [], 't', 'old'));
45 }
46
47 public function testIncomingBinding(): void
48 {
49 $binder = new ExpressionBinder(new \ZtdQuery\Platform\MySql\Sql\MySqlIdentifierQuoter(), \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create());
50 $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize('VALUES(score)', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens();
51 self::assertSame(['offset' => 0, 'length' => 13, 'value' => '`__ztd_incoming`.`score`', 'skip' => 7], $binder->incomingBinding($tokens, 0));
52 self::assertNull($binder->incomingBinding(\ZtdQuery\Sql\SqlTokenStream::tokenize('VALUES(1 + 2)', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens(), 0));
53 }
54
55 public function testQualifiedBinding(): void
56 {
57 $binder = new ExpressionBinder(new \ZtdQuery\Platform\MySql\Sql\MySqlIdentifierQuoter(), \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create());
58 $tokens = \ZtdQuery\Sql\SqlTokenStream::tokenize('t.score', \ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::create())->significantTokens();
59 self::assertSame(['offset' => 0, 'length' => 7, 'value' => '`old`.`score`'], $binder->qualifiedBinding($tokens[0], $tokens[2], 'old'));
60 }
61
62}
63