sql_utils: improved table_from_sql

This commit is contained in:
Mickey Rose 2017-02-08 17:30:25 +01:00
parent a4e8ea21be
commit 2587bb3a1d

View file

@ -33,8 +33,8 @@
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
// stl // stl
#include <sstream> #include <iosfwd>
#include <vector> #include <regex>
#include <string> #include <string>
namespace mapnik { namespace sql_utils { namespace mapnik { namespace sql_utils {
@ -125,6 +125,69 @@ namespace mapnik { namespace sql_utils {
s << ",\"" << field << "\""; s << ",\"" << field << "\"";
} }
const std::regex re_from{
"\\bFROM\\b"
, std::regex::icase
};
const std::regex re_table_name{
"\\s*(\\w+|(\"[^\"]*\")+)" // $1 = schema
"(\\.(\\w+|(\"[^\"]*\")+))?" // $4 = table
"\\s*"
};
inline bool table_from_sql(std::string const& sql,
std::string & schema,
std::string & table)
{
std::smatch m;
auto start = sql.begin();
auto end = sql.end();
auto flags = std::regex_constants::match_default;
auto found = std::regex_match(start, end, m, re_table_name);
auto extract_matched_parts = [&]()
{
if (m[4].matched)
{
table.assign(m[4].first, m[4].second);
schema.assign(m[1].first, m[1].second);
}
else
{
table.assign(m[1].first, m[1].second);
schema.clear();
}
};
if (found)
{
// input is not subquery, just "[schema.]table"
extract_matched_parts();
}
else
{
// search "FROM [schema.]table" in subquery
while (std::regex_search(start, end, m, re_from, flags))
{
start = m[0].second;
if (std::regex_search(start, end, m, re_table_name,
std::regex_constants::match_continuous))
{
extract_matched_parts();
found = true;
start = m[0].second;
}
flags = std::regex_constants::match_prev_avail;
}
}
if (found)
{
sql_utils::unquote('"', schema);
sql_utils::unquote('"', table);
}
return found;
}
inline std::string table_from_sql(std::string const& sql) inline std::string table_from_sql(std::string const& sql)
{ {
std::string table_name = sql; std::string table_name = sql;