ql_template::Parser: Introduce 'CleanSections'

This commit is contained in:
lganzzzo 2020-12-23 03:11:37 +02:00
parent 72a1536050
commit 2b9f0d9455
3 changed files with 255 additions and 51 deletions

View File

@ -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<CleanSection>& 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) "<!!", 3, true)) {
sectionStart = ss.getCurrentPosition();
writeChar = false;
} else {
caret.inc();
}
} else {
caret.inc();
}
break;
}
case ']': {
caret.inc();
if(ignore) {
ignore = !(caret.canContinue() && caret.isAtChar('>'));
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<CleanSection> cleanSections;
auto processedText = preprocess(text, cleanSections);
parser::Caret caret(processedText);
std::vector<data::share::StringTemplate::Variable> 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));
}

View File

@ -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<CleanSection>& cleanSections);
/**
* Parse query template.

View File

@ -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<Parser::CleanSection> 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<Parser::CleanSection> 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<Parser::CleanSection> 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 = "<!!SELECT * FROM my_table;!!>";
std::vector<Parser::CleanSection> 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<Parser::CleanSection> 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<Parser::CleanSection> 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 == 6);
}
}
{
oatpp::String text = "SELECT < !! * !! > FROM!!> my_table;";
std::vector<Parser::CleanSection> 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 <!! schedule[1:2][2] !!> FROM <!!my_table!!>;";
std::vector<Parser::CleanSection> 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<Parser::CleanSection> 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 '<!!' * <!! FROM!!> my_table;";
std::vector<Parser::CleanSection> 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 == 15);
OATPP_ASSERT(s.size == 5);
}
}
{
oatpp::String text = "SELECT * <!!!!> FROM my_table;";
std::vector<Parser::CleanSection> 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 <!! name::text !!> FROM my_table WHERE id=:id;";
std::vector<Parser::CleanSection> sections;
auto temp = Parser::parseTemplate(text);
auto result = temp.format("<val>");
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=<val>;");
}
{
oatpp::String text = "SELECT <!! name::text !!> FROM my_table WHERE <!! id=:id !!>;";
std::vector<Parser::CleanSection> sections;
auto temp = Parser::parseTemplate(text);
auto result = temp.format("<val>");
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 ;");
}
}