dbms: added support for hex escape sequences in strings [#METR-19072].

This commit is contained in:
Alexey Milovidov 2015-11-25 06:11:17 +03:00
parent c39a17e65a
commit 8c8210062a
6 changed files with 71 additions and 63 deletions

View File

@ -1,8 +1,12 @@
#pragma once
#include <string>
#include <DB/IO/ReadHelpers.h>
namespace DB
{
inline std::string escapeForFileName(const std::string & s)
{
std::string res;
@ -30,25 +34,13 @@ inline std::string escapeForFileName(const std::string & s)
return res;
}
inline char unhex(char c)
{
switch (c)
{
case '0' ... '9':
return c - '0';
case 'A' ... 'F':
return c - 'A' + 10;
default:
return 0;
}
}
inline std::string unescapeForFileName(const std::string & s)
{
std::string res;
const char * pos = s.data();
const char * end = pos + s.size();
while (pos != end)
{
if (*pos != '%')
@ -57,17 +49,19 @@ inline std::string unescapeForFileName(const std::string & s)
{
/// пропустим '%'
if (++pos == end) break;
char val = unhex(*pos) * 16;
if (++pos == end) break;
val += unhex(*pos);
res += val;
}
++pos;
}
return res;
}
}

View File

@ -28,7 +28,7 @@ namespace DB
/// Функции-помошники для форматированного чтения
static inline char parseEscapeSequence(char c)
inline char parseEscapeSequence(char c)
{
switch(c)
{
@ -49,6 +49,21 @@ static inline char parseEscapeSequence(char c)
}
}
inline char unhex(char c)
{
switch (c)
{
case '0' ... '9':
return c - '0';
case 'a' ... 'f':
return c - 'a' + 10;
case 'A' ... 'F':
return c - 'A' + 10;
default:
return 0;
}
}
/// Эти функции находятся в VarInt.h
/// inline void throwReadAfterEOF()

View File

@ -142,6 +142,34 @@ static inline const char * find_first_tab_lf_or_backslash(const char * begin, co
}
/** Распарсить escape-последовательность, которая может быть простой (один символ после бэкслеша) или более сложной (несколько символов).
* Предполагается, что курсор расположен на символе \
*/
static void parseComplexEscapeSequence(String & s, ReadBuffer & buf)
{
++buf.position();
if (buf.eof())
throw Exception("Cannot parse escape sequence", ErrorCodes::CANNOT_PARSE_ESCAPE_SEQUENCE);
if (*buf.position() == 'x')
{
++buf.position();
/// escape-последовательность вида \xAA
UInt8 c1;
UInt8 c2;
readPODBinary(c1, buf);
readPODBinary(c2, buf);
s += static_cast<char>(unhex(c1) * 16 + unhex(c2));
}
else
{
/// Обычная escape-последовательность из одного символа.
s += parseEscapeSequence(*buf.position());
++buf.position();
}
}
void readEscapedString(DB::String & s, DB::ReadBuffer & buf)
{
s = "";
@ -159,13 +187,7 @@ void readEscapedString(DB::String & s, DB::ReadBuffer & buf)
return;
if (*buf.position() == '\\')
{
++buf.position();
if (buf.eof())
throw Exception("Cannot parse escape sequence", DB::ErrorCodes::CANNOT_PARSE_ESCAPE_SEQUENCE);
s += DB::parseEscapeSequence(*buf.position());
++buf.position();
}
parseComplexEscapeSequence(s, buf);
}
}
@ -233,13 +255,7 @@ static void readAnyQuotedString(String & s, ReadBuffer & buf)
}
if (*buf.position() == '\\')
{
++buf.position();
if (buf.eof())
throw Exception("Cannot parse escape sequence", ErrorCodes::CANNOT_PARSE_ESCAPE_SEQUENCE);
s += parseEscapeSequence(*buf.position());
++buf.position();
}
parseComplexEscapeSequence(s, buf);
}
throw Exception("Cannot parse quoted string: expected closing quote",

View File

@ -375,40 +375,21 @@ bool ParserStringLiteral::parseImpl(Pos & pos, Pos end, ASTPtr & node, Pos & max
return false;
}
++pos;
ReadBuffer in(const_cast<char *>(pos), end - pos, 0);
while (pos != end)
try
{
size_t bytes = 0;
for (; pos + bytes != end; ++bytes)
if (pos[bytes] == '\\' || pos[bytes] == '\'')
break;
s.append(pos, bytes);
pos += bytes;
if (*pos == '\'')
{
++pos;
node = new ASTLiteral(StringRange(begin, pos), s);
return true;
}
if (*pos == '\\')
{
++pos;
if (pos == end)
{
expected = "escape sequence";
return false;
}
s += parseEscapeSequence(*pos);
++pos;
}
readQuotedString(s, in);
}
catch (const Exception & e)
{
expected = "string literal";
return false;
}
expected = "closing single quote";
return false;
pos += in.count();
node = new ASTLiteral(StringRange(begin, pos), s);
return true;
}

View File

@ -0,0 +1 @@
0 Р

View File

@ -0,0 +1 @@
SELECT '\x30 \xD0\xA0';