diff --git a/src/oatpp-postgresql/ql_template/Parser.cpp b/src/oatpp-postgresql/ql_template/Parser.cpp index edd0d66..26fc550 100644 --- a/src/oatpp-postgresql/ql_template/Parser.cpp +++ b/src/oatpp-postgresql/ql_template/Parser.cpp @@ -29,14 +29,15 @@ namespace oatpp { namespace postgresql { namespace ql_template { -oatpp::String Parser::preprocess(const oatpp::String& text) { +oatpp::String Parser::preprocess(const oatpp::String& text, std::vector& cleanSections) { data::stream::BufferOutputStream ss; parser::Caret caret(text); - bool ignore = false; bool writeChar = true; + v_buff_size sectionStart = -1; + while(caret.canContinue()) { v_char8 c = *caret.getCurrData(); @@ -58,26 +59,32 @@ oatpp::String Parser::preprocess(const oatpp::String& text) { writeChar = false; break; } + case '<': { - caret.inc(); - if(!ignore) { - ignore = caret.canContinue() && caret.isAtChar('['); - if(ignore) { - caret.inc(); + if(sectionStart == -1) { + if(caret.isAtText((p_char8) "')); - if(!ignore) { - caret.inc(); + case '!': { + if(sectionStart != -1) { + if(caret.isAtText((p_char8) "!!>", 3, true)) { + cleanSections.emplace_back(CleanSection(sectionStart, ss.getCurrentPosition() - sectionStart)); + sectionStart = -1; writeChar = false; + } else { + caret.inc(); } + } else { + caret.inc(); } break; } @@ -88,11 +95,7 @@ oatpp::String Parser::preprocess(const oatpp::String& text) { } if(writeChar) { - if (ignore) { - ss.writeCharSimple('_'); - } else { - ss.writeCharSimple(c); - } + ss.writeCharSimple(c); } } @@ -172,11 +175,23 @@ void Parser::skipStringInDollars(parser::Caret& caret) { data::share::StringTemplate Parser::parseTemplate(const oatpp::String& text) { + std::vector cleanSections; + auto processedText = preprocess(text, cleanSections); + + parser::Caret caret(processedText); + std::vector variables; - parser::Caret caret(preprocess(text)); + v_buff_size currSection = 0; + while(caret.canContinue()) { + if(currSection < cleanSections.size() && cleanSections[currSection].position == caret.getPosition()) { + caret.inc(cleanSections[currSection].size); + currSection ++; + continue; + } + v_char8 c = *caret.getCurrData(); switch(c) { @@ -203,7 +218,7 @@ data::share::StringTemplate Parser::parseTemplate(const oatpp::String& text) { throw oatpp::parser::ParsingError(caret.getErrorMessage(), caret.getErrorCode(), caret.getPosition()); } - return data::share::StringTemplate(text, std::move(variables)); + return data::share::StringTemplate(processedText, std::move(variables)); } diff --git a/src/oatpp-postgresql/ql_template/Parser.hpp b/src/oatpp-postgresql/ql_template/Parser.hpp index 29e2ee5..42e5f72 100644 --- a/src/oatpp-postgresql/ql_template/Parser.hpp +++ b/src/oatpp-postgresql/ql_template/Parser.hpp @@ -65,6 +65,16 @@ public: }; +public: + + struct CleanSection { + CleanSection(v_buff_size p, v_buff_size s) + : position(p) + , size(s) + {} + v_buff_size position; + v_buff_size size; + }; private: static data::share::StringTemplate::Variable parseIdentifier(parser::Caret& caret); @@ -75,9 +85,10 @@ public: /** * Preprocess text. * @param text + * @param cleanSections - out vector of clean sections. * @return */ - static oatpp::String preprocess(const oatpp::String& text); + static oatpp::String preprocess(const oatpp::String& text, std::vector& cleanSections); /** * Parse query template. diff --git a/test/oatpp-postgresql/ql_template/ParserTest.cpp b/test/oatpp-postgresql/ql_template/ParserTest.cpp index 706a320..58e5ad8 100644 --- a/test/oatpp-postgresql/ql_template/ParserTest.cpp +++ b/test/oatpp-postgresql/ql_template/ParserTest.cpp @@ -36,49 +36,227 @@ typedef oatpp::postgresql::ql_template::Parser Parser; void ParserTest::onRun() { -// { -// oatpp::String text = ""; -// auto result = Parser::preprocess(text); -// OATPP_ASSERT(result == text); -// } -// -// { -// oatpp::String text = "SELECT * FROM my_table;"; -// auto result = Parser::preprocess(text); -// OATPP_ASSERT(result == text); -// } - { - oatpp::String text = "SELECT <[ * ]> FROM my_table;"; - auto result = Parser::preprocess(text); - OATPP_ASSERT(result == "SELECT ___ FROM my_table;"); + oatpp::String text = ""; + std::vector sections; + auto result = Parser::preprocess(text, sections); + + OATPP_LOGD(TAG, "--- case ---"); + OATPP_LOGD(TAG, "sql='%s'", text->c_str()); + OATPP_LOGD(TAG, "res='%s'", result->c_str()); + + OATPP_ASSERT(result == text); + } { - oatpp::String text = "<[SELECT * FROM my_table;]>"; - auto result = Parser::preprocess(text); - OATPP_ASSERT(result == "_______________________"); + oatpp::String text = "SELECT * FROM my_table;"; + std::vector sections; + auto result = Parser::preprocess(text, sections); + + OATPP_LOGD(TAG, "--- case ---"); + OATPP_LOGD(TAG, "sql='%s'", text->c_str()); + OATPP_LOGD(TAG, "res='%s'", result->c_str()); + + OATPP_ASSERT(result == text); + } { - oatpp::String text = "SELECT <[ * ]> FROM]> my_table;"; - auto result = Parser::preprocess(text); - OATPP_LOGD(TAG, "sql='%s'", text->getData()); - OATPP_LOGD(TAG, "res='%s'", result->getData()); + oatpp::String text = "SELECT FROM my_table;"; + std::vector sections; + auto result = Parser::preprocess(text, sections); + + OATPP_LOGD(TAG, "--- case ---"); + OATPP_LOGD(TAG, "sql='%s'", text->c_str()); + OATPP_LOGD(TAG, "res='%s'", result->c_str()); + + OATPP_ASSERT(sections.size() == 1); + OATPP_ASSERT(result == "SELECT * FROM my_table;"); + { + const auto& s = sections[0]; + OATPP_ASSERT(s.position == 7); + OATPP_ASSERT(s.size == 3); + } } { - oatpp::String text = "SELECT < [ * ] > FROM]> my_table;"; - auto result = Parser::preprocess(text); - OATPP_LOGD(TAG, "sql='%s'", text->getData()); - OATPP_LOGD(TAG, "res='%s'", result->getData()); + oatpp::String text = ""; + std::vector sections; + auto result = Parser::preprocess(text, sections); + + OATPP_LOGD(TAG, "--- case ---"); + OATPP_LOGD(TAG, "sql='%s'", text->c_str()); + OATPP_LOGD(TAG, "res='%s'", result->c_str()); + + OATPP_ASSERT(sections.size() == 1); + OATPP_ASSERT(result == "SELECT * FROM my_table;"); + { + const auto& s = sections[0]; + OATPP_ASSERT(s.position == 0); + OATPP_ASSERT(s.size == result->getSize()); + } } { - oatpp::String text = "SELECT <[ * ']>' FROM my_table;"; - auto result = Parser::preprocess(text); - OATPP_LOGD(TAG, "sql='%s'", text->getData()); - OATPP_LOGD(TAG, "res='%s'", result->getData()); + oatpp::String text = "SELECT FROM!!> my_table;"; + std::vector sections; + auto result = Parser::preprocess(text, sections); + + OATPP_LOGD(TAG, "--- case ---"); + OATPP_LOGD(TAG, "sql='%s'", text->c_str()); + OATPP_LOGD(TAG, "res='%s'", result->c_str()); + + OATPP_ASSERT(sections.size() == 1); + OATPP_ASSERT(result == "SELECT * FROM!!> my_table;"); + { + const auto& s = sections[0]; + OATPP_ASSERT(s.position == 7); + OATPP_ASSERT(s.size == 3); + } + } + + { + oatpp::String text = "SELECT FROM!!> my_table;"; + std::vector sections; + auto result = Parser::preprocess(text, sections); + + OATPP_LOGD(TAG, "--- case ---"); + OATPP_LOGD(TAG, "sql='%s'", text->c_str()); + OATPP_LOGD(TAG, "res='%s'", result->c_str()); + + OATPP_ASSERT(sections.size() == 1); + OATPP_ASSERT(result == "SELECT my_table;"); + { + const auto& s = sections[0]; + OATPP_ASSERT(s.position == 7); + OATPP_ASSERT(s.size == 6); + } + } + + { + oatpp::String text = "SELECT < !! * !! > FROM!!> my_table;"; + std::vector sections; + auto result = Parser::preprocess(text, sections); + + OATPP_LOGD(TAG, "--- case ---"); + OATPP_LOGD(TAG, "sql='%s'", text->c_str()); + OATPP_LOGD(TAG, "res='%s'", result->c_str()); + + OATPP_ASSERT(sections.size() == 0); + OATPP_ASSERT(result == text); + } + + { + oatpp::String text = "SELECT FROM ;"; + std::vector sections; + auto result = Parser::preprocess(text, sections); + + OATPP_LOGD(TAG, "--- case ---"); + OATPP_LOGD(TAG, "sql='%s'", text->c_str()); + OATPP_LOGD(TAG, "res='%s'", result->c_str()); + + OATPP_ASSERT(sections.size() == 2); + OATPP_ASSERT(result == "SELECT schedule[1:2][2] FROM my_table;"); + + { + const auto& s = sections[0]; + OATPP_ASSERT(s.position == 7); + OATPP_ASSERT(s.size == 18); + } + + { + const auto& s = sections[1]; + OATPP_ASSERT(s.position == 31); + OATPP_ASSERT(s.size == 8); + } + + } + + { + oatpp::String text = "SELECT ' FROM!!> my_table;"; + std::vector sections; + auto result = Parser::preprocess(text, sections); + + OATPP_LOGD(TAG, "--- case ---"); + OATPP_LOGD(TAG, "sql='%s'", text->c_str()); + OATPP_LOGD(TAG, "res='%s'", result->c_str()); + + OATPP_ASSERT(sections.size() == 1); + OATPP_ASSERT(result == "SELECT * '!!>' FROM my_table;"); + + { + const auto& s = sections[0]; + OATPP_ASSERT(s.position == 7); + OATPP_ASSERT(s.size == 13); + } + + } + + { + oatpp::String text = "SELECT ' my_table;"; + std::vector sections; + auto result = Parser::preprocess(text, sections); + + OATPP_LOGD(TAG, "--- case ---"); + OATPP_LOGD(TAG, "sql='%s'", text->c_str()); + OATPP_LOGD(TAG, "res='%s'", result->c_str()); + + OATPP_ASSERT(sections.size() == 1); + OATPP_ASSERT(result == "SELECT ' FROM my_table;"; + std::vector sections; + auto result = Parser::preprocess(text, sections); + + OATPP_LOGD(TAG, "--- case ---"); + OATPP_LOGD(TAG, "sql='%s'", text->c_str()); + OATPP_LOGD(TAG, "res='%s'", result->c_str()); + + OATPP_ASSERT(sections.size() == 1); + OATPP_ASSERT(result == "SELECT * FROM my_table;"); + + { + const auto& s = sections[0]; + OATPP_ASSERT(s.position == 9); + OATPP_ASSERT(s.size == 0); + } + + } + + { + oatpp::String text = "SELECT FROM my_table WHERE id=:id;"; + std::vector sections; + auto temp = Parser::parseTemplate(text); + auto result = temp.format(""); + + OATPP_LOGD(TAG, "--- case ---"); + OATPP_LOGD(TAG, "sql='%s'", text->c_str()); + OATPP_LOGD(TAG, "res='%s'", result->c_str()); + + OATPP_ASSERT(result == "SELECT name::text FROM my_table WHERE id=;"); + } + + { + oatpp::String text = "SELECT FROM my_table WHERE ;"; + std::vector sections; + auto temp = Parser::parseTemplate(text); + auto result = temp.format(""); + + OATPP_LOGD(TAG, "--- case ---"); + OATPP_LOGD(TAG, "sql='%s'", text->c_str()); + OATPP_LOGD(TAG, "res='%s'", result->c_str()); + + OATPP_ASSERT(result == "SELECT name::text FROM my_table WHERE id=:id ;"); } }