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