Don't use system locale when parsing SQL statements

Antlr uses the current system locale when parsing SQL statements. This
is problematic because SQL is case-independent and for converting
characters to lower/upper case it is going to use the locale. For
Turkish however this adds implicit conversions between the dotted and
dotless I which triggers another problem in Antlr: it doesn't cover the
whole Unicode character set. This commit fixes the implicit conversions.

See issue #1194.
This commit is contained in:
Martin Kleusberg
2017-10-26 23:27:17 +02:00
parent 18b781495c
commit 56630a20e5

View File

@@ -45,6 +45,36 @@ QDataStream& operator>>(QDataStream& ds, ObjectIdentifier& objid)
return ds;
}
/**
* @brief The SetLocaleToC class
* This is a stupid helper class which sets the current locale as used by the C++ standard library to the C locale.
* Upon destruction it resets it to whatever the previous locale was. This is used to work around a problem in Antlr's
* string comparison which because it is case-independent relies on the current locale. However, when parsind SQL
* statements we don't want the locale to interfere here. Especially the Turkish locale is problematic here because
* of the dotted I problem.
*/
class SetLocaleToC
{
public:
SetLocaleToC()
{
// Query current locale and save it
oldLocale = std::setlocale(LC_CTYPE, nullptr);
// Set locale for standard library functions
std::setlocale(LC_CTYPE, "C.UTF-8");
}
~SetLocaleToC()
{
// Reset old locale
std::setlocale(LC_CTYPE, oldLocale.c_str());
}
private:
std::string oldLocale;
};
/**
* @brief The CreateTableWalker class
* Goes trough the createtable AST and returns
@@ -420,6 +450,8 @@ bool Table::hasAutoIncrement() const
ObjectPtr Table::parseSQL(const QString &sSQL)
{
SetLocaleToC locale;
std::stringstream s;
s << sSQL.toStdString();
Sqlite3Lexer lex(s);
@@ -1219,6 +1251,8 @@ FieldInfoList Index::fieldInformation() const
ObjectPtr Index::parseSQL(const QString& sSQL)
{
SetLocaleToC locale;
std::stringstream s;
s << sSQL.toStdString();
Sqlite3Lexer lex(s);