diff --git a/dbms/src/Parsers/formatAST.cpp b/dbms/src/Parsers/formatAST.cpp index e3122b2abd5..2df3f96a4aa 100644 --- a/dbms/src/Parsers/formatAST.cpp +++ b/dbms/src/Parsers/formatAST.cpp @@ -4,7 +4,7 @@ #include -#include +#include #include #include @@ -27,7 +27,7 @@ public: String operator() (const String & x) const { std::stringstream s; - s << strconvert::quote_fast << x; + s << mysqlxx::quote << x; return s.str(); } diff --git a/dbms/src/Parsers/tests/parsers.cpp b/dbms/src/Parsers/tests/parsers.cpp index 57f7c87ab2a..633a87bbd4e 100644 --- a/dbms/src/Parsers/tests/parsers.cpp +++ b/dbms/src/Parsers/tests/parsers.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include #include @@ -27,7 +27,7 @@ int main(int argc, char ** argv) else { std::cout << "Failed at position " << (pos - begin) << ": " - << strconvert::quote_fast << input.substr(pos - begin, 10) + << mysqlxx::quote << input.substr(pos - begin, 10) << ", expected " << expected << "." << std::endl; } diff --git a/libs/libmysqlxx/include/mysqlxx/Manip.h b/libs/libmysqlxx/include/mysqlxx/Manip.h index 2c305aec6c6..09f6464b710 100644 --- a/libs/libmysqlxx/include/mysqlxx/Manip.h +++ b/libs/libmysqlxx/include/mysqlxx/Manip.h @@ -3,8 +3,10 @@ #include #include + #include #include +#include namespace mysqlxx @@ -232,6 +234,221 @@ inline QuoteManipResult operator<< (std::ostream & ostr, quote_enum manip) { return QuoteManipResult(ostr); } + + +/** Манипулятор istream, позволяет считывать значения из tab delimited файла. + */ +enum unescape_enum +{ + unescape +}; + + +/** Манипулятор istream, который позволяет читать значения в кавычках или без. + */ +enum unquote_enum +{ + unquote +}; + + +inline void parseEscapeSequence(std::istream & istr, std::string & value) +{ + char c = istr.get(); + if (!istr.good()) + throw Poco::Exception("Cannot parse string: unexpected end of input."); + + switch(c) + { + case 'b': + value.push_back('\b'); + break; + case 'f': + value.push_back('\f'); + break; + case 'n': + value.push_back('\n'); + break; + case 'r': + value.push_back('\r'); + break; + case 't': + value.push_back('\t'); + break; + default: + value.push_back(c); + break; + } +} + + +struct UnEscapeManipResult +{ + std::istream & istr; + + UnEscapeManipResult(std::istream & istr_) : istr(istr_) {} + + std::istream & operator>> (bool & value) { return istr >> value; } + std::istream & operator>> (char & value) { return istr >> value; } + std::istream & operator>> (unsigned char & value) { return istr >> value; } + std::istream & operator>> (signed char & value) { return istr >> value; } + std::istream & operator>> (short & value) { return istr >> value; } + std::istream & operator>> (unsigned short & value) { return istr >> value; } + std::istream & operator>> (int & value) { return istr >> value; } + std::istream & operator>> (unsigned int & value) { return istr >> value; } + std::istream & operator>> (long & value) { return istr >> value; } + std::istream & operator>> (unsigned long & value) { return istr >> value; } + std::istream & operator>> (float & value) { return istr >> value; } + std::istream & operator>> (double & value) { return istr >> value; } + std::istream & operator>> (long long & value) { return istr >> value; } + std::istream & operator>> (unsigned long long & value) { return istr >> value; } + + std::istream & operator>> (std::string & value) + { + value.clear(); + + char c; + while (1) + { + istr.get(c); + if (!istr.good()) + break; + + switch (c) + { + case '\\': + parseEscapeSequence(istr, value); + break; + + case '\t': + istr.unget(); + return istr; + break; + + case '\n': + istr.unget(); + return istr; + break; + + default: + value.push_back(c); + break; + } + } + return istr; + } + + /// Чтение NULL-able типа. + template + std::istream & operator>> (Null & value) + { + char c; + istr.get(c); + if (c == '\\' && istr.peek() == 'N') + { + value.is_null = true; + istr.ignore(); + } + else + { + istr.unget(); + value.is_null = false; + *this >> value.data; + } + return istr; + } + + std::istream & operator>> (Date & value) + { + std::string s; + (*this) >> s; + value = Date(s); + return istr; + } + + std::istream & operator>> (DateTime & value) + { + std::string s; + (*this) >> s; + value = DateTime(s); + return istr; + } +}; + +inline UnEscapeManipResult operator>> (std::istream & istr, unescape_enum manip) +{ + return UnEscapeManipResult(istr); +} + + +struct UnQuoteManipResult +{ +public: + std::istream & istr; + + UnQuoteManipResult(std::istream & istr_) : istr(istr_) {} + + std::istream & operator>> (bool & value) { return istr >> value; } + std::istream & operator>> (char & value) { return istr >> value; } + std::istream & operator>> (unsigned char & value) { return istr >> value; } + std::istream & operator>> (signed char & value) { return istr >> value; } + std::istream & operator>> (short & value) { return istr >> value; } + std::istream & operator>> (unsigned short & value) { return istr >> value; } + std::istream & operator>> (int & value) { return istr >> value; } + std::istream & operator>> (unsigned int & value) { return istr >> value; } + std::istream & operator>> (long & value) { return istr >> value; } + std::istream & operator>> (unsigned long & value) { return istr >> value; } + std::istream & operator>> (float & value) { return istr >> value; } + std::istream & operator>> (double & value) { return istr >> value; } + std::istream & operator>> (long long & value) { return istr >> value; } + std::istream & operator>> (unsigned long long & value) { return istr >> value; } + + std::istream & operator>> (std::string & value) + { + value.clear(); + readQuote(); + + char c; + while (1) + { + istr.get(c); + if (!istr.good()) + break; + + switch (c) + { + case '\\': + parseEscapeSequence(istr, value); + break; + + case '\'': + return istr; + break; + + default: + value.push_back(c); + break; + } + } + throw Poco::Exception("Cannot parse string: unexpected end of input."); + } +private: + + void readQuote() + { + char c = istr.get(); + if (!istr.good()) + throw Poco::Exception("Cannot parse string: unexpected end of input."); + if (c != '\'') + throw Poco::Exception("Cannot parse string: missing opening single quote."); + } +}; + +inline UnQuoteManipResult operator>> (std::istream & istr, unquote_enum manip) +{ + return UnQuoteManipResult(istr); +} + } diff --git a/libs/libmysqlxx/src/tests/mysqlxx_test.cpp b/libs/libmysqlxx/src/tests/mysqlxx_test.cpp index 6d891a39099..3f683f1c53f 100644 --- a/libs/libmysqlxx/src/tests/mysqlxx_test.cpp +++ b/libs/libmysqlxx/src/tests/mysqlxx_test.cpp @@ -1,7 +1,6 @@ #include #include #include -#include int main(int argc, char ** argv) @@ -29,8 +28,8 @@ int main(int argc, char ** argv) << std::endl << mysqlxx::escape << row[1].getDate() << ", " << mysqlxx::escape << row[1].getDateTime() << std::endl << mysqlxx::quote << row[1].getDate() << ", " << mysqlxx::quote << row[1].getDateTime() << std::endl - << strconvert::escape_file << row[1].getDate() << ", " << strconvert::escape_file << row[1].getDateTime() << std::endl - << strconvert::quote_fast << row[1].getDate() << ", " << strconvert::quote_fast << row[1].getDateTime() << std::endl + << mysqlxx::escape << row[1].getDate() << ", " << mysqlxx::escape << row[1].getDateTime() << std::endl + << mysqlxx::quote << row[1].getDate() << ", " << mysqlxx::quote << row[1].getDateTime() << std::endl ; time_t t1 = row[0];