2012-05-08 05:42:05 +00:00
|
|
|
#include <sstream>
|
|
|
|
|
2012-09-24 05:40:45 +00:00
|
|
|
#include <mysqlxx/Manip.h>
|
|
|
|
|
|
|
|
#include <DB/Core/Defines.h>
|
2010-06-04 18:25:25 +00:00
|
|
|
#include <DB/IO/ReadHelpers.h>
|
|
|
|
|
2012-05-08 05:42:05 +00:00
|
|
|
|
2010-06-04 18:25:25 +00:00
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2012-09-24 05:40:45 +00:00
|
|
|
|
|
|
|
static void __attribute__((__noinline__)) throwAtAssertionFailed(const char * s, ReadBuffer & buf)
|
|
|
|
{
|
|
|
|
std::stringstream message;
|
|
|
|
message << "Cannot parse input: expected " << mysqlxx::escape << s;
|
|
|
|
|
|
|
|
if (buf.eof())
|
|
|
|
message << " at end of stream.";
|
|
|
|
else
|
|
|
|
message << " before: " << mysqlxx::escape << String(buf.position(), std::min(SHOW_CHARS_ON_SYNTAX_ERROR, buf.buffer().end() - buf.position()));
|
|
|
|
|
|
|
|
throw Exception(message.str(), ErrorCodes::CANNOT_PARSE_INPUT_ASSERTION_FAILED);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-04 18:25:25 +00:00
|
|
|
void assertString(const char * s, ReadBuffer & buf)
|
|
|
|
{
|
|
|
|
for (; *s; ++s)
|
|
|
|
{
|
|
|
|
if (buf.eof() || *buf.position() != *s)
|
2012-09-24 05:40:45 +00:00
|
|
|
throwAtAssertionFailed(s, buf);
|
2010-06-04 18:25:25 +00:00
|
|
|
++buf.position();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void readString(String & s, ReadBuffer & buf)
|
|
|
|
{
|
|
|
|
s = "";
|
|
|
|
while (!buf.eof())
|
|
|
|
{
|
|
|
|
size_t bytes = 0;
|
|
|
|
for (; buf.position() + bytes != buf.buffer().end(); ++bytes)
|
|
|
|
if (buf.position()[bytes] == '\t' || buf.position()[bytes] == '\n')
|
|
|
|
break;
|
|
|
|
|
|
|
|
s.append(buf.position(), bytes);
|
|
|
|
buf.position() += bytes;
|
|
|
|
|
|
|
|
if (buf.position() != buf.buffer().end())
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void readEscapedString(String & s, ReadBuffer & buf)
|
|
|
|
{
|
|
|
|
s = "";
|
|
|
|
while (!buf.eof())
|
|
|
|
{
|
|
|
|
size_t bytes = 0;
|
|
|
|
for (; buf.position() + bytes != buf.buffer().end(); ++bytes)
|
|
|
|
if (buf.position()[bytes] == '\\' || buf.position()[bytes] == '\t' || buf.position()[bytes] == '\n')
|
|
|
|
break;
|
|
|
|
|
|
|
|
s.append(buf.position(), bytes);
|
|
|
|
buf.position() += bytes;
|
|
|
|
|
2011-12-26 02:17:33 +00:00
|
|
|
if (buf.position() == buf.buffer().end())
|
|
|
|
continue;
|
|
|
|
|
2010-06-04 18:25:25 +00:00
|
|
|
if (*buf.position() == '\t' || *buf.position() == '\n')
|
|
|
|
return;
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-15 18:54:18 +00:00
|
|
|
|
|
|
|
template <char quote>
|
|
|
|
static void readAnyQuotedString(String & s, ReadBuffer & buf)
|
2010-06-04 18:25:25 +00:00
|
|
|
{
|
|
|
|
s = "";
|
|
|
|
|
2011-06-15 18:54:18 +00:00
|
|
|
if (buf.eof() || *buf.position() != quote)
|
|
|
|
throw Exception("Cannot parse quoted string: expected opening quote",
|
2010-06-04 18:25:25 +00:00
|
|
|
ErrorCodes::CANNOT_PARSE_QUOTED_STRING);
|
|
|
|
++buf.position();
|
|
|
|
|
|
|
|
while (!buf.eof())
|
|
|
|
{
|
|
|
|
size_t bytes = 0;
|
|
|
|
for (; buf.position() + bytes != buf.buffer().end(); ++bytes)
|
2011-06-15 18:54:18 +00:00
|
|
|
if (buf.position()[bytes] == '\\' || buf.position()[bytes] == quote)
|
2010-06-04 18:25:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
s.append(buf.position(), bytes);
|
|
|
|
buf.position() += bytes;
|
|
|
|
|
2011-12-26 02:17:33 +00:00
|
|
|
if (buf.position() == buf.buffer().end())
|
|
|
|
continue;
|
|
|
|
|
2011-06-15 18:54:18 +00:00
|
|
|
if (*buf.position() == quote)
|
2010-06-04 18:25:25 +00:00
|
|
|
{
|
|
|
|
++buf.position();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-15 18:54:18 +00:00
|
|
|
throw Exception("Cannot parse quoted string: expected closing quote",
|
2010-06-04 18:25:25 +00:00
|
|
|
ErrorCodes::CANNOT_PARSE_QUOTED_STRING);
|
|
|
|
}
|
|
|
|
|
2011-06-15 18:54:18 +00:00
|
|
|
|
|
|
|
void readQuotedString(String & s, ReadBuffer & buf)
|
|
|
|
{
|
|
|
|
readAnyQuotedString<'\''>(s, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
void readDoubleQuotedString(String & s, ReadBuffer & buf)
|
|
|
|
{
|
|
|
|
readAnyQuotedString<'"'>(s, buf);
|
|
|
|
}
|
|
|
|
|
2011-11-01 17:57:37 +00:00
|
|
|
void readBackQuotedString(String & s, ReadBuffer & buf)
|
|
|
|
{
|
|
|
|
readAnyQuotedString<'`'>(s, buf);
|
|
|
|
}
|
|
|
|
|
2012-05-08 05:42:05 +00:00
|
|
|
|
|
|
|
void readException(Exception & e, ReadBuffer & buf, const String & additional_message)
|
|
|
|
{
|
|
|
|
int code = 0;
|
|
|
|
String name;
|
|
|
|
String message;
|
|
|
|
String stack_trace;
|
|
|
|
bool has_nested = false;
|
|
|
|
|
|
|
|
readBinary(code, buf);
|
|
|
|
readBinary(name, buf);
|
|
|
|
readBinary(message, buf);
|
|
|
|
readBinary(stack_trace, buf);
|
|
|
|
readBinary(has_nested, buf);
|
|
|
|
|
|
|
|
std::stringstream message_stream;
|
|
|
|
|
|
|
|
if (!additional_message.empty())
|
|
|
|
message_stream << additional_message << ". ";
|
|
|
|
|
|
|
|
if (name != "DB::Exception")
|
|
|
|
message_stream << name << ". ";
|
|
|
|
|
|
|
|
message_stream << message
|
|
|
|
<< ". Stack trace:\n\n" << stack_trace;
|
|
|
|
|
|
|
|
if (has_nested)
|
|
|
|
{
|
|
|
|
Exception nested;
|
|
|
|
readException(nested, buf);
|
|
|
|
e = Exception(message_stream.str(), nested, code);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
e = Exception(message_stream.str(), code);
|
|
|
|
}
|
|
|
|
|
|
|
|
void readAndThrowException(ReadBuffer & buf, const String & additional_message)
|
|
|
|
{
|
|
|
|
Exception e;
|
|
|
|
readException(e, buf, additional_message);
|
|
|
|
e.rethrow();
|
|
|
|
}
|
|
|
|
|
2010-06-04 18:25:25 +00:00
|
|
|
}
|