Skip to content

Commit ad53b05

Browse files
committed
Build insert statement with context's quote style
1 parent 707e336 commit ad53b05

File tree

4 files changed

+59
-52
lines changed

4 files changed

+59
-52
lines changed

phpstan-baseline.neon

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,11 @@ parameters:
485485
count: 1
486486
path: src/Components/IntoKeyword.php
487487

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

psalm-baseline.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@
247247
<MoreSpecificImplementedParamType occurrences="1">
248248
<code>$component</code>
249249
</MoreSpecificImplementedParamType>
250+
<PossiblyInvalidArgument occurrences="1">
251+
<code>Context::escape($component-&gt;columns)</code>
252+
</PossiblyInvalidArgument>
250253
<PossiblyInvalidPropertyFetch occurrences="1">
251254
<code>ArrayObj::parse($parser, $list)-&gt;values</code>
252255
</PossiblyInvalidPropertyFetch>

src/Components/IntoKeyword.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PhpMyAdmin\SqlParser\Components;
66

77
use PhpMyAdmin\SqlParser\Component;
8+
use PhpMyAdmin\SqlParser\Context;
89
use PhpMyAdmin\SqlParser\Parser;
910
use PhpMyAdmin\SqlParser\Token;
1011
use PhpMyAdmin\SqlParser\TokensList;
@@ -271,7 +272,9 @@ public function parseFileOptions(Parser $parser, TokensList $list, $keyword = 'F
271272
public static function build($component, array $options = [])
272273
{
273274
if ($component->dest instanceof Expression) {
274-
$columns = ! empty($component->columns) ? '(`' . implode('`, `', $component->columns) . '`)' : '';
275+
$columns = $component->columns === null || $component->columns === []
276+
? ''
277+
: '(' . implode(', ', Context::escape($component->columns)) . ')';
275278

276279
return $component->dest . $columns;
277280
}

tests/Builder/InsertStatementTest.php

Lines changed: 47 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4,64 +4,60 @@
44

55
namespace PhpMyAdmin\SqlParser\Tests\Builder;
66

7+
use Generator;
8+
use PhpMyAdmin\SqlParser\Context;
79
use PhpMyAdmin\SqlParser\Parser;
810
use PhpMyAdmin\SqlParser\Tests\TestCase;
911

1012
class InsertStatementTest extends TestCase
1113
{
12-
public function testBuilder(): void
14+
/** @var int */
15+
private $sqlMode;
16+
17+
public function setUp(): void
1318
{
14-
/* Assertion 1 */
15-
$parser = new Parser('INSERT INTO tbl(`col1`, `col2`, `col3`) VALUES (1, "str", 3.14)');
16-
$stmt = $parser->statements[0];
17-
$this->assertEquals(
18-
'INSERT INTO tbl(`col1`, `col2`, `col3`) VALUES (1, "str", 3.14)',
19-
$stmt->build()
20-
);
21-
22-
/* Assertion 2 */
23-
/* Reserved keywords (with backquotes as field name) */
24-
$parser = new Parser('INSERT INTO tbl(`order`) VALUES (1)');
25-
$stmt = $parser->statements[0];
26-
$this->assertEquals(
27-
'INSERT INTO tbl(`order`) VALUES (1)',
28-
$stmt->build()
29-
);
30-
31-
/* Assertion 3 */
32-
/* INSERT ... SET ... */
33-
$parser = new Parser('INSERT INTO tbl SET FOO = 1');
34-
$stmt = $parser->statements[0];
35-
$this->assertEquals(
36-
'INSERT INTO tbl SET FOO = 1',
37-
$stmt->build()
38-
);
39-
40-
/* Assertion 4 */
41-
/* INSERT ... SELECT ... */
42-
$parser = new Parser('INSERT INTO tbl SELECT * FROM bar');
43-
$stmt = $parser->statements[0];
44-
$this->assertEquals(
45-
'INSERT INTO tbl SELECT * FROM bar',
46-
$stmt->build()
47-
);
48-
49-
/* Assertion 5 */
50-
/* INSERT ... ON DUPLICATE KEY UPDATE ... */
51-
$parser = new Parser('INSERT INTO tbl SELECT * FROM bar ON DUPLICATE KEY UPDATE baz = 1');
19+
parent::setUp();
20+
21+
$this->sqlMode = Context::getMode();
22+
}
23+
24+
protected function tearDown(): void
25+
{
26+
Context::setMode($this->sqlMode);
27+
28+
parent::tearDown();
29+
}
30+
31+
/** @dataProvider providerForTestBuilder */
32+
public function testBuilder(string $sql): void
33+
{
34+
$parser = new Parser($sql);
5235
$stmt = $parser->statements[0];
53-
$this->assertEquals(
54-
'INSERT INTO tbl SELECT * FROM bar ON DUPLICATE KEY UPDATE baz = 1',
55-
$stmt->build()
56-
);
57-
58-
/* Assertion 6 */
59-
/* INSERT [OPTIONS] INTO ... */
60-
$parser = new Parser('INSERT DELAYED IGNORE INTO tbl SELECT * FROM bar');
36+
$this->assertEquals($sql, $stmt->build());
37+
}
38+
39+
/** @return Generator<string, list<string>> */
40+
public function providerForTestBuilder(): Generator
41+
{
42+
yield 'INSERT ... VALUES ...' => ['INSERT INTO tbl(`col1`, `col2`, `col3`) VALUES (1, "str", 3.14)'];
43+
44+
yield 'Reserved keywords (with backquotes as field name)' => ['INSERT INTO tbl(`order`) VALUES (1)'];
45+
46+
yield 'INSERT ... SET ...' => ['INSERT INTO tbl SET FOO = 1'];
47+
48+
yield 'INSERT ... SELECT ... ' => ['INSERT INTO tbl SELECT * FROM bar'];
49+
50+
yield 'INSERT ... ON DUPLICATE KEY UPDATE ...' => ['INSERT INTO tbl SELECT * FROM bar ON DUPLICATE KEY UPDATE baz = 1'];
51+
52+
yield 'INSERT [OPTIONS] INTO ...' => ['INSERT DELAYED IGNORE INTO tbl SELECT * FROM bar'];
53+
}
54+
55+
public function testBuilderAnsi(): void
56+
{
57+
Context::setMode(Context::SQL_MODE_ANSI);
58+
$sql = "INSERT INTO foo (bar, baz) VALUES ('bar', 'baz')";
59+
$parser = new Parser($sql);
6160
$stmt = $parser->statements[0];
62-
$this->assertEquals(
63-
'INSERT DELAYED IGNORE INTO tbl SELECT * FROM bar',
64-
$stmt->build()
65-
);
61+
$this->assertEquals('INSERT INTO foo("bar", "baz") VALUES (\'bar\', \'baz\')', $stmt->build());
6662
}
6763
}

0 commit comments

Comments
 (0)