Skip to content

Commit 7d28b7b

Browse files
committed
Build insert statement with context's quote style
1 parent 4652d80 commit 7d28b7b

File tree

3 files changed

+61
-47
lines changed

3 files changed

+61
-47
lines changed

src/Components/IntoKeyword.php

Lines changed: 2 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,7 @@ 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 ? '(' . implode(', ', Context::escapeAll($component->columns)) . ')' : '';
275276

276277
return $component->dest . $columns;
277278
}

src/Context.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -803,7 +803,7 @@ private static function getModeFromString(string $mode): int
803803
}
804804

805805
/**
806-
* Escapes the symbol by adding surrounding backticks.
806+
* Escapes the symbol according to the curren sql mode.
807807
*
808808
* @param string[]|string $str the string to be escaped
809809
* @param string $quote quote to be used when escaping
@@ -831,6 +831,18 @@ public static function escape($str, $quote = '`')
831831
return $quote . str_replace($quote, $quote . $quote, $str) . $quote;
832832
}
833833

834+
/**
835+
* Escapes the symbol according to the curren sql mode.
836+
*
837+
* @param string[] $strings the string to be escaped
838+
*
839+
* @return string[]
840+
*/
841+
public static function escapeAll(array $strings): array
842+
{
843+
return array_map([Context::class, 'escape'], $strings);
844+
}
845+
834846
/**
835847
* Returns char used to quote identifiers based on currently set SQL Mode (ie. standard or ANSI_QUOTES)
836848
*

tests/Builder/InsertStatementTest.php

Lines changed: 46 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,64 +4,65 @@
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+
private int $mode;
15+
16+
public function setUp(): void
1317
{
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-
);
18+
parent::setUp();
2119

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-
);
20+
$this->mode = Context::getMode();
21+
}
3022

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-
);
23+
protected function tearDown(): void
24+
{
25+
Context::setMode($this->mode);
3926

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-
);
27+
parent::tearDown();
28+
}
4829

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');
30+
/** @dataProvider providerForTestBuilder */
31+
public function testBuilder(string $sql): void
32+
{
33+
$parser = new Parser($sql);
5234
$stmt = $parser->statements[0];
53-
$this->assertEquals(
35+
$this->assertEquals($sql, $stmt->build());
36+
}
37+
38+
public function providerForTestBuilder(): Generator
39+
{
40+
yield 'INSERT ... VALUES ...' => [
41+
'INSERT INTO tbl(`col1`, `col2`, `col3`) VALUES (1, "str", 3.14)',
42+
];
43+
yield 'Reserved keywords (with backquotes as field name)' => [
44+
'INSERT INTO tbl(`order`) VALUES (1)',
45+
];
46+
yield 'INSERT ... SET ...' => [
47+
'INSERT INTO tbl SET FOO = 1',
48+
];
49+
yield 'INSERT ... SELECT ... ' => [
50+
'INSERT INTO tbl SELECT * FROM bar',
51+
];
52+
yield 'INSERT ... ON DUPLICATE KEY UPDATE ...' => [
5453
'INSERT INTO tbl SELECT * FROM bar ON DUPLICATE KEY UPDATE baz = 1',
55-
$stmt->build()
56-
);
54+
];
55+
yield 'INSERT [OPTIONS] INTO ...' => [
56+
'INSERT DELAYED IGNORE INTO tbl SELECT * FROM bar',
57+
];
58+
}
5759

58-
/* Assertion 6 */
59-
/* INSERT [OPTIONS] INTO ... */
60-
$parser = new Parser('INSERT DELAYED IGNORE INTO tbl SELECT * FROM bar');
60+
public function testBuilderAnsi(): void
61+
{
62+
Context::setMode(Context::SQL_MODE_ANSI);
63+
$sql = "INSERT INTO foo (bar, baz) VALUES ('bar', 'baz')";
64+
$parser = new Parser($sql);
6165
$stmt = $parser->statements[0];
62-
$this->assertEquals(
63-
'INSERT DELAYED IGNORE INTO tbl SELECT * FROM bar',
64-
$stmt->build()
65-
);
66+
$this->assertEquals('INSERT INTO foo("bar", "baz") VALUES (\'bar\', \'baz\')', $stmt->build());
6667
}
6768
}

0 commit comments

Comments
 (0)