Skip to content

Commit b2b13c6

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

File tree

3 files changed

+62
-47
lines changed

3 files changed

+62
-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: 47 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,64 +4,66 @@
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-
);
19+
parent::setUp();
2120

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-
);
21+
$this->sqlMode = Context::getMode();
22+
}
3023

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

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

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

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

0 commit comments

Comments
 (0)