Skip to content

Commit 839cda3

Browse files
committed
Provide limited support for NO_BACKSLASH_ESCAPES SQL mode
1 parent 648174d commit 839cda3

File tree

3 files changed

+55
-23
lines changed

3 files changed

+55
-23
lines changed

src/Io/Query.php

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,23 @@ class Query
1919
* Note that this mapping assumes an ASCII-compatible charset encoding such
2020
* as UTF-8, ISO 8859 and others.
2121
*
22+
* Note that `'` will be escaped as `''` instead of `\'` to provide some
23+
* limited support for the `NO_BACKSLASH_ESCAPES` SQL mode. This assumes all
24+
* strings will always be enclosed in `'` instead of `"` which is guaranteed
25+
* as long as this class is only used internally for the `query()` method.
26+
*
2227
* @var array<string,string>
2328
* @see \React\MySQL\Commands\AuthenticateCommand::$charsetMap
2429
*/
2530
private $escapeChars = [
26-
"\x00" => "\\0",
27-
"\r" => "\\r",
28-
"\n" => "\\n",
29-
"\t" => "\\t",
31+
//"\x00" => "\\0",
32+
//"\r" => "\\r",
33+
//"\n" => "\\n",
34+
//"\t" => "\\t",
3035
//"\b" => "\\b",
3136
//"\x1a" => "\\Z",
32-
"'" => "\'",
33-
'"' => '\"',
37+
"'" => "''",
38+
//'"' => '\"',
3439
"\\" => "\\\\",
3540
//"%" => "\\%",
3641
//"_" => "\\_",

tests/Io/QueryTest.php

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,9 @@ public function testEscapeChars()
6666
{
6767
$query = new Query('');
6868
$this->assertEquals('\\\\', $query->escape('\\'));
69-
$this->assertEquals('\"', $query->escape('"'));
70-
$this->assertEquals("\'", $query->escape("'"));
71-
$this->assertEquals("\\n", $query->escape("\n"));
72-
$this->assertEquals("\\r", $query->escape("\r"));
73-
$this->assertEquals("foo\\0bar", $query->escape("foo" . chr(0) . "bar"));
69+
$this->assertEquals("''", $query->escape("'"));
70+
$this->assertEquals("foo\0bar", $query->escape("foo" . chr(0) . "bar"));
7471
$this->assertEquals("n%3A", $query->escape("n%3A"));
75-
//$this->assertEquals('§ä¨ì¥H¤U¤º®e\\\\§ä¨ì¥H¤U¤º®e', $query->escape('§ä¨ì¥H¤U¤º®e\\§ä¨ì¥H¤U¤º®e'));
72+
$this->assertEquals('§ä¨ì¥H¤U¤º®e\\\\§ä¨ì¥H¤U¤º®e', $query->escape('§ä¨ì¥H¤U¤º®e\\§ä¨ì¥H¤U¤º®e'));
7673
}
7774
}

tests/ResultQueryTest.php

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,42 +32,72 @@ public function provideValuesThatWillBeReturnedAsIs()
3232
'hello?',
3333
'FööBär',
3434
'pile of 💩',
35-
'<>&--\\\'";',
36-
"\0\1\2\3\4\5\6\7\8\xff",
35+
'Dave\'s Diner',
36+
'Robert "Bobby"',
37+
"first\r\nsecond",
38+
'C:\\\\Users\\',
39+
'<>&--\'";',
40+
"\0\1\2\3\4\5\6\7\10\xff",
41+
implode('', range("\x00", "\x2F")) . implode('', range("\x7f", "\xFF")),
3742
'',
3843
null
3944
]);
4045
}
4146

42-
public function provideValuesThatWillBeConvertedToString()
47+
/**
48+
* @dataProvider provideValuesThatWillBeReturnedAsIs
49+
*/
50+
public function testSelectStaticValueWillBeReturnedAsIs($value)
4351
{
44-
return [
45-
[1, '1'],
46-
[1.5, '1.5'],
47-
[true, '1'],
48-
[false, '0']
49-
];
52+
$connection = $this->createConnection(Loop::get());
53+
54+
$expected = $value;
55+
56+
$connection->query('select ?', [$value])->then(function (QueryResult $command) use ($expected) {
57+
$this->assertCount(1, $command->resultRows);
58+
$this->assertCount(1, $command->resultRows[0]);
59+
$this->assertSame($expected, reset($command->resultRows[0]));
60+
})->then(null, 'printf');
61+
62+
$connection->quit();
63+
Loop::run();
5064
}
5165

5266
/**
5367
* @dataProvider provideValuesThatWillBeReturnedAsIs
5468
*/
55-
public function testSelectStaticValueWillBeReturnedAsIs($value)
69+
public function testSelectStaticValueWillBeReturnedAsIsWithNoBackslashEscapesSqlMode($value)
5670
{
71+
if (strpos($value, '\\') !== false) {
72+
// TODO: strings such as '%\\' work as-is when string contains percent?!
73+
$this->markTestIncomplete('Escaping backslash not supported when using NO_BACKSLASH_ESCAPES SQL mode');
74+
}
75+
5776
$connection = $this->createConnection(Loop::get());
5877

5978
$expected = $value;
6079

80+
$connection->query('SET SQL_MODE="NO_BACKSLASH_ESCAPES"');
6181
$connection->query('select ?', [$value])->then(function (QueryResult $command) use ($expected) {
6282
$this->assertCount(1, $command->resultRows);
6383
$this->assertCount(1, $command->resultRows[0]);
6484
$this->assertSame($expected, reset($command->resultRows[0]));
65-
});
85+
})->then(null, 'printf');
6686

6787
$connection->quit();
6888
Loop::run();
6989
}
7090

91+
public function provideValuesThatWillBeConvertedToString()
92+
{
93+
return [
94+
[1, '1'],
95+
[1.5, '1.5'],
96+
[true, '1'],
97+
[false, '0']
98+
];
99+
}
100+
71101
/**
72102
* @dataProvider provideValuesThatWillBeConvertedToString
73103
*/

0 commit comments

Comments
 (0)