packages/ztd-query-mysql/tests/Unit/Rewrite/LoadData/ColumnMappingTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Rewrite\LoadData;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\TestCase;
9use ZtdQuery\Platform\MySql\Rewrite\LoadData\ColumnMapping;
10
11#[\PHPUnit\Framework\Attributes\UsesClass(\ZtdQuery\Platform\MySql\Sql\MySqlLexerProfile::class)]
12#[CoversClass(ColumnMapping::class)]
13final class ColumnMappingTest extends TestCase
14{
15    public function testInputTargets(): void
16    {
17        $sql = "LOAD DATA INFILE 'input.csv' INTO TABLE t (id, @raw)";
18        $statement = (new \PhpMyAdmin\SqlParser\Parser($sql))->statements[0];
19        self::assertInstanceOf(\PhpMyAdmin\SqlParser\Statements\LoadStatement::class, $statement);
20        $definition = new \ZtdQuery\Schema\TableDefinition(['id', 'name', 'score'], [], [], [], [], generatedExpressions: ['score' => 'id * 2']);
21        self::assertSame(['id', '@raw'], (new ColumnMapping())->inputTargets($statement, $definition, $sql));
22        $statement->col_name_or_user_var = null;
23        self::assertSame(['id', 'name'], (new ColumnMapping())->inputTargets($statement, $definition, $sql));
24    }
25
26    public function testInputTarget(): void
27    {
28        $mapping = new ColumnMapping();
29        self::assertSame('name', $mapping->inputTarget('`name`', 'LOAD DATA'));
30        self::assertSame('@raw', $mapping->inputTarget('@`raw`', 'LOAD DATA'));
31    }
32
33    public function testInputTargetRejectsExpressions(): void
34    {
35        $this->expectException(\ZtdQuery\Exception\UnsupportedSqlException::class);
36        (new ColumnMapping())->inputTarget('id + 1', 'LOAD DATA');
37    }
38
39    public function testSetOperations(): void
40    {
41        $sql = "LOAD DATA INFILE 'input.csv' INTO TABLE t SET name = UPPER(@raw)";
42        $statement = (new \PhpMyAdmin\SqlParser\Parser($sql))->statements[0];
43        self::assertInstanceOf(\PhpMyAdmin\SqlParser\Statements\LoadStatement::class, $statement);
44        $definition = new \ZtdQuery\Schema\TableDefinition(['id', 'name', 'score'], [], [], [], [], generatedExpressions: ['score' => 'id * 2']);
45        self::assertSame(['name' => 'UPPER(@raw)'], (new ColumnMapping())->setOperations($statement, $definition, $sql));
46    }
47
48    public function testIgnoreRows(): void
49    {
50        $sql = "LOAD DATA INFILE 'input.csv' INTO TABLE t IGNORE 2 LINES";
51        $statement = (new \PhpMyAdmin\SqlParser\Parser($sql))->statements[0];
52        self::assertInstanceOf(\PhpMyAdmin\SqlParser\Statements\LoadStatement::class, $statement);
53        self::assertSame(2, (new ColumnMapping())->ignoreRows($statement, $sql));
54        $statement->ignore_number = null;
55        self::assertSame(0, (new ColumnMapping())->ignoreRows($statement, $sql));
56    }
57
58    public function testOptionValue(): void
59    {
60        $sql = "LOAD DATA INFILE 'input.csv' INTO TABLE t FIELDS TERMINATED BY ','";
61        $statement = (new \PhpMyAdmin\SqlParser\Parser($sql))->statements[0];
62        self::assertInstanceOf(\PhpMyAdmin\SqlParser\Statements\LoadStatement::class, $statement);
63        $mapping = new ColumnMapping();
64        self::assertSame(',', $mapping->optionValue($statement->fields_options, 'TERMINATED BY', "\t"));
65        self::assertSame('fallback', $mapping->optionValue($statement->fields_options, 'ENCLOSED BY', 'fallback'));
66        self::assertSame('fallback', $mapping->optionValue(null, 'TERMINATED BY', 'fallback'));
67    }
68
69}
70