packages/ztd-query-mysql/src/Sql/OptionalInsertIntoNormalizer.php

1<?php
2
3declare(strict_types=1);
4
5namespace ZtdQuery\Platform\MySql\Sql;
6
7use PhpMyAdmin\SqlParser\Lexer;
8use PhpMyAdmin\SqlParser\Token;
9
10/**
11 * Optional Insert Into Normalizer.
12 *
13 * @visibility ZtdQuery\Platform\MySql
14 */
15final class OptionalInsertIntoNormalizer
16{
17    /**
18     * Normalize Optional Insert Into for the supplied MySQL input.
19     */
20    public function normalizeOptionalInsertInto(string $sql): string
21    {
22        $tokens = [];
23        foreach (Lexer::getTokens($sql)->tokens as $token) {
24            if (in_array($token->type, [Token::TYPE_WHITESPACE, Token::TYPE_COMMENT, Token::TYPE_DELIMITER], true)) {
25                continue;
26            }
27            $tokens[] = $token;
28        }
29
30        $insert = $tokens[0] ?? null;
31        if ($insert === null || $insert->keyword !== 'INSERT') {
32            return $sql;
33        }
34
35        $targetIndex = 1;
36        while (isset($tokens[$targetIndex]) && in_array(
37            $tokens[$targetIndex]->keyword,
38            ['LOW_PRIORITY', 'DELAYED', 'HIGH_PRIORITY', 'IGNORE'],
39            true,
40        )) {
41            $targetIndex++;
42        }
43
44        $target = $tokens[$targetIndex] ?? $insert;
45        if (!in_array($target->type, [Token::TYPE_NONE, Token::TYPE_SYMBOL], true)) {
46            return $sql;
47        }
48        if (!is_int($target->position)) {
49            return $sql;
50        }
51
52        return substr($sql, 0, $target->position) . 'INTO ' . substr($sql, $target->position);
53    }
54}
55