66#include < sstream>
77#include < iostream>
88#include < clocale> // This include seems to only be necessary for the Windows build
9- #include < regex>
109#include < numeric>
1110
11+ namespace {
12+ bool starts_with_ci (const std::string& str, const std::string& with)
13+ {
14+ if (str.size () < with.size ())
15+ return false ;
16+ else
17+ return compare_ci (str.substr (0 , with.size ()), with);
18+ }
19+ }
20+
1221namespace sqlb {
1322
1423StringVector escapeIdentifier (StringVector ids)
@@ -235,32 +244,55 @@ std::string Field::toString(const std::string& indent, const std::string& sep) c
235244
236245bool Field::isText () const
237246{
238- std::regex is_text (" (^(character|varchar|varying character|nchar|native character|nvarchar))|(^(text|clob)$)" , std::regex::icase);
239- return std::regex_match (m_type, is_text);
247+ if (starts_with_ci (m_type, " character" )) return true ;
248+ if (starts_with_ci (m_type, " varchar" )) return true ;
249+ if (starts_with_ci (m_type, " varying character" )) return true ;
250+ if (starts_with_ci (m_type, " nchar" )) return true ;
251+ if (starts_with_ci (m_type, " native character" )) return true ;
252+ if (starts_with_ci (m_type, " nvarchar" )) return true ;
253+ if (compare_ci (m_type, " text" )) return true ;
254+ if (compare_ci (m_type, " clob" )) return true ;
255+ return false ;
240256}
241257
242258bool Field::isInteger () const
243259{
244- std::regex is_integer (" ^(int|integer|tinyint|smallint|mediumint|bigint|unsigned big int|int2|int8)$" , std::regex::icase);
245- return std::regex_match (m_type, is_integer);
260+ if (compare_ci (m_type, " int" )) return true ;
261+ if (compare_ci (m_type, " integer" )) return true ;
262+ if (compare_ci (m_type, " tinyint" )) return true ;
263+ if (compare_ci (m_type, " smallint" )) return true ;
264+ if (compare_ci (m_type, " mediumint" )) return true ;
265+ if (compare_ci (m_type, " bigint" )) return true ;
266+ if (compare_ci (m_type, " unsigned big int" )) return true ;
267+ if (compare_ci (m_type, " int2" )) return true ;
268+ if (compare_ci (m_type, " int8" )) return true ;
269+ return false ;
246270}
247271
248272bool Field::isReal () const
249273{
250- std::regex is_real (" ^(real|double|double precision|float)$" , std::regex::icase);
251- return std::regex_match (m_type, is_real);
274+ if (compare_ci (m_type, " real" )) return true ;
275+ if (compare_ci (m_type, " double" )) return true ;
276+ if (compare_ci (m_type, " double precision" )) return true ;
277+ if (compare_ci (m_type, " float" )) return true ;
278+ return false ;
252279}
253280
254281bool Field::isNumeric () const
255282{
256- std::regex is_numeric (" (^(decimal))|(^(numeric|boolean|date|datetime)$)" , std::regex::icase);
257- return std::regex_match (m_type, is_numeric);
283+ if (starts_with_ci (m_type, " decimal" )) return true ;
284+ if (compare_ci (m_type, " numeric" )) return true ;
285+ if (compare_ci (m_type, " boolean" )) return true ;
286+ if (compare_ci (m_type, " date" )) return true ;
287+ if (compare_ci (m_type, " datetime" )) return true ;
288+ return false ;
258289}
259290
260291bool Field::isBlob () const
261292{
262- std::regex is_blob (" (^$)|(^blob$)" , std::regex::icase);
263- return std::regex_match (m_type, is_blob);
293+ if (m_type.empty ()) return true ;
294+ if (compare_ci (m_type, " blob" )) return true ;
295+ return false ;
264296}
265297
266298std::string Field::affinity () const
@@ -591,6 +623,19 @@ void Table::renameKeyInAllConstraints(const std::string& key, const std::string&
591623
592624namespace
593625{
626+ std::string unescape_identifier (std::string str, char quote_char)
627+ {
628+ std::string quote (2 , quote_char);
629+
630+ size_t pos = 0 ;
631+ while ((pos = str.find (quote, pos)) != std::string::npos)
632+ {
633+ str.erase (pos, 1 );
634+ pos += 1 ; // Don't remove the other quote char too
635+ }
636+ return str;
637+ }
638+
594639std::string identifier (antlr::RefAST ident)
595640{
596641 std::string sident = ident->getText ();
@@ -599,7 +644,7 @@ std::string identifier(antlr::RefAST ident)
599644 ident->getType () == sqlite3TokenTypes::STRINGLITERAL)
600645 {
601646 // Remember the way the identifier is quoted
602- std::string quoteChar ( 1 , sident.at (0 ) );
647+ char quoteChar = sident.at (0 );
603648
604649 // Remove first and final character, i.e. the quotes
605650 sident = sident.substr (1 , sident.size () - 2 );
@@ -608,7 +653,7 @@ std::string identifier(antlr::RefAST ident)
608653 // by a single instance. This is done because two quotes can be used as a means of escaping
609654 // the quote character, thus only the visual representation has its two quotes, the actual
610655 // name contains only one.
611- sident = std::regex_replace (sident, std::regex ( " \\ " + quoteChar + " \\ " + quoteChar) , quoteChar);
656+ sident = unescape_identifier (sident, quoteChar);
612657 }
613658
614659 return sident;
0 commit comments