Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ parameters:
path: src/Components/IntoKeyword.php

-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
message: "#^Parameter \\#2 \\$pieces of function implode expects array, array\\<string\\>\\|string given\\.$#"
count: 1
path: src/Components/IntoKeyword.php

Expand Down Expand Up @@ -2140,11 +2140,6 @@ parameters:
count: 10
path: tests/Builder/ExplainStatementTest.php

-
message: "#^Dynamic call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertEquals\\(\\)\\.$#"
count: 6
path: tests/Builder/InsertStatementTest.php

-
message: "#^Dynamic call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertEquals\\(\\)\\.$#"
count: 6
Expand Down
3 changes: 3 additions & 0 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,9 @@
<MoreSpecificImplementedParamType occurrences="1">
<code>$component</code>
</MoreSpecificImplementedParamType>
<PossiblyInvalidArgument occurrences="1">
<code>Context::escape($component-&gt;columns)</code>
</PossiblyInvalidArgument>
<PossiblyInvalidPropertyFetch occurrences="1">
<code>ArrayObj::parse($parser, $list)-&gt;values</code>
</PossiblyInvalidPropertyFetch>
Expand Down
5 changes: 4 additions & 1 deletion src/Components/IntoKeyword.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace PhpMyAdmin\SqlParser\Components;

use PhpMyAdmin\SqlParser\Component;
use PhpMyAdmin\SqlParser\Context;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Token;
use PhpMyAdmin\SqlParser\TokensList;
Expand Down Expand Up @@ -271,7 +272,9 @@ public function parseFileOptions(Parser $parser, TokensList $list, $keyword = 'F
public static function build($component, array $options = [])
{
if ($component->dest instanceof Expression) {
$columns = ! empty($component->columns) ? '(`' . implode('`, `', $component->columns) . '`)' : '';
$columns = $component->columns === null || $component->columns === []
? ''
: '(' . implode(', ', Context::escape($component->columns)) . ')';

return $component->dest . $columns;
}
Expand Down
99 changes: 48 additions & 51 deletions tests/Builder/InsertStatementTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,64 +4,61 @@

namespace PhpMyAdmin\SqlParser\Tests\Builder;

use Generator;
use PhpMyAdmin\SqlParser\Context;
use PhpMyAdmin\SqlParser\Parser;
use PhpMyAdmin\SqlParser\Tests\TestCase;

class InsertStatementTest extends TestCase
{
public function testBuilder(): void
/** @var int */
private $sqlMode;

public function setUp(): void
{
/* Assertion 1 */
$parser = new Parser('INSERT INTO tbl(`col1`, `col2`, `col3`) VALUES (1, "str", 3.14)');
$stmt = $parser->statements[0];
$this->assertEquals(
'INSERT INTO tbl(`col1`, `col2`, `col3`) VALUES (1, "str", 3.14)',
$stmt->build()
);

/* Assertion 2 */
/* Reserved keywords (with backquotes as field name) */
$parser = new Parser('INSERT INTO tbl(`order`) VALUES (1)');
$stmt = $parser->statements[0];
$this->assertEquals(
'INSERT INTO tbl(`order`) VALUES (1)',
$stmt->build()
);

/* Assertion 3 */
/* INSERT ... SET ... */
$parser = new Parser('INSERT INTO tbl SET FOO = 1');
$stmt = $parser->statements[0];
$this->assertEquals(
'INSERT INTO tbl SET FOO = 1',
$stmt->build()
);

/* Assertion 4 */
/* INSERT ... SELECT ... */
$parser = new Parser('INSERT INTO tbl SELECT * FROM bar');
$stmt = $parser->statements[0];
$this->assertEquals(
'INSERT INTO tbl SELECT * FROM bar',
$stmt->build()
);

/* Assertion 5 */
/* INSERT ... ON DUPLICATE KEY UPDATE ... */
$parser = new Parser('INSERT INTO tbl SELECT * FROM bar ON DUPLICATE KEY UPDATE baz = 1');
parent::setUp();

$this->sqlMode = Context::getMode();
}

protected function tearDown(): void
{
Context::setMode($this->sqlMode);

parent::tearDown();
}

/** @dataProvider providerForTestBuilder */
public function testBuilder(string $sql): void
{
$parser = new Parser($sql);
$stmt = $parser->statements[0];
$this->assertEquals(
'INSERT INTO tbl SELECT * FROM bar ON DUPLICATE KEY UPDATE baz = 1',
$stmt->build()
);

/* Assertion 6 */
/* INSERT [OPTIONS] INTO ... */
$parser = new Parser('INSERT DELAYED IGNORE INTO tbl SELECT * FROM bar');
self::assertEquals($sql, $stmt->build());
}

/** @return Generator<string, list<string>> */
public function providerForTestBuilder(): Generator
{
yield 'INSERT ... VALUES ...' => ['INSERT INTO tbl(`col1`, `col2`, `col3`) VALUES (1, "str", 3.14)'];

yield 'Reserved keywords (with backquotes as field name)' => ['INSERT INTO tbl(`order`) VALUES (1)'];

yield 'INSERT ... SET ...' => ['INSERT INTO tbl SET FOO = 1'];

yield 'INSERT ... SELECT ... ' => ['INSERT INTO tbl SELECT * FROM bar'];

yield 'INSERT ... ON DUPLICATE KEY UPDATE ...' =>
['INSERT INTO tbl SELECT * FROM bar ON DUPLICATE KEY UPDATE baz = 1'];

yield 'INSERT [OPTIONS] INTO ...' => ['INSERT DELAYED IGNORE INTO tbl SELECT * FROM bar'];
}

public function testBuilderAnsi(): void
{
Context::setMode(Context::SQL_MODE_ANSI_QUOTES);
$sql = "INSERT INTO foo (bar, baz) VALUES ('bar', 'baz')";
$parser = new Parser($sql);
$stmt = $parser->statements[0];
$this->assertEquals(
'INSERT DELAYED IGNORE INTO tbl SELECT * FROM bar',
$stmt->build()
);
self::assertEquals('INSERT INTO foo("bar", "baz") VALUES (\'bar\', \'baz\')', $stmt->build());
}
}