packages/ztd-query-mysql/src/Sql/Upsert/AssignmentReader.php
1<?php
2
3declare(strict_types=1);
4
5namespace ZtdQuery\Platform\MySql\Sql\Upsert;
6
7use ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile;
8use ZtdQuery\Sql\SqlToken;
9use ZtdQuery\Sql\SqlTokenKind;
10use ZtdQuery\Sql\SqlTokenStream;
11
12/**
13 * Assignment Reader.
14 *
15 * @visibility ZtdQuery\Platform\MySql
16 */
17final class AssignmentReader
18{
19 /**
20 * @return array{column: string, value: string}|null
21 */
22 public function assignment(string $assignment): ?array
23 {
24 $tokens = SqlTokenStream::tokenize($assignment, MySqlLexerProfile::create())->significantTokens();
25 foreach ($tokens as $index => $token) {
26 if ($token->kind !== SqlTokenKind::Symbol || $token->text !== '=' || !$token->isTopLevel()) {
27 continue;
28 }
29 $column = $this->lastIdentifier(array_slice($tokens, 0, $index));
30 $value = trim(substr($assignment, $token->endOffset()));
31 if ($column === null || $value === '') {
32 return null;
33 }
34
35 return ['column' => $column, 'value' => $value];
36 }
37
38 return null;
39 }
40
41 /**
42 * @param list<SqlToken> $tokens
43 */
44 public function lastIdentifier(array $tokens): ?string
45 {
46 $token = array_pop($tokens);
47 return $token !== null
48 ? SqlTokenStream::tokenize($token->text, MySqlLexerProfile::create())->identifierAt()['name'] ?? null
49 : null;
50 }
51}
52