From 2fe3327c8e2db027febb2acfc115d1602a71ad61 Mon Sep 17 00:00:00 2001 From: cxl Date: Wed, 20 Aug 2008 10:06:42 +0000 Subject: [PATCH] Fixed encoding issues in MySql, new ExportIds utility (in Sql) creates a file of SQLID constants for given database git-svn-id: svn://ultimatepp.org/upp/trunk@361 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/MySql/MySql.cpp | 40 +++++++++++++++++++++++++++++----------- uppsrc/Sql/ExportSch.cpp | 33 ++++++++++++++++++++++++++++++++- uppsrc/Sql/SqlSchema.h | 2 ++ uppsrc/Sql/Sqlexp.h | 11 ++++++----- 4 files changed, 69 insertions(+), 17 deletions(-) diff --git a/uppsrc/MySql/MySql.cpp b/uppsrc/MySql/MySql.cpp index 0a36e15cb..081285b84 100644 --- a/uppsrc/MySql/MySql.cpp +++ b/uppsrc/MySql/MySql.cpp @@ -26,9 +26,11 @@ private: unsigned long *len; int rows; int lastid; + Buffer convert; String MakeQuery() const; void FreeResult(); + String EscapeString(const String& v); public: MySqlConnection(MySqlSession& session, MYSQL *mysql); @@ -49,6 +51,8 @@ bool MySqlSession::Connect(const char *user, const char *password, const char *d sEmpNull(socket), 0)) { Sql sql(*this); username = sql.Select("substring_index(USER(),'@',1)"); + sql.Execute("SET NAMES 'utf8'"); + sql.Execute("SET CHARACTER SET utf8"); return true; } Close(); @@ -182,23 +186,29 @@ MySqlConnection::MySqlConnection(MySqlSession& session, MYSQL *mysql) lastid = 0; } +String MySqlConnection::EscapeString(const String& v) +{ + StringBuffer b(v.GetLength() * 2 + 3); + char *q = b; + *q = '\"'; + int n = mysql_real_escape_string(mysql, q + 1, v, v.GetLength()); + q[1 + n] = '\"'; + b.SetCount(2 + n); //TODO - check this fix + return b; +} + void MySqlConnection::SetParam(int i, const Value& r) { String p; if(IsNull(r)) p = "NULL"; else switch(r.GetType()) { + case 34: + p = EscapeString(SqlRaw(r)); + break; case WSTRING_V: - case STRING_V: { - String v = r; - StringBuffer b(v.GetLength() * 2 + 3); - char *q = b; - *q = '\"'; - int n = mysql_real_escape_string(mysql, q + 1, v, v.GetLength()); - q[1 + n] = '\"'; - b.SetCount(2 + n); //TODO - check this fix - p = b; - } + case STRING_V: + p = EscapeString(ToCharset(CHARSET_UTF8, r)); break; case BOOL_V: case INT_V: @@ -257,6 +267,7 @@ bool MySqlConnection::Execute() { rows = (int)mysql_affected_rows(mysql); int fields = mysql_num_fields(result); info.SetCount(fields); + convert.Alloc(fields, false); for(int i = 0; i < fields; i++) { MYSQL_FIELD *field = mysql_fetch_field_direct(result, i); SqlColumnInfo& f = info[i]; @@ -280,8 +291,12 @@ bool MySqlConnection::Execute() { case FIELD_TYPE_DATETIME: f.type = TIME_V; break; + case FIELD_TYPE_VAR_STRING: + case FIELD_TYPE_STRING: + convert[i] = true; default: f.type = STRING_V; + break; } f.width = field->length; f.scale = f.precision = 0; @@ -361,7 +376,10 @@ void MySqlConnection::GetColumn(int i, Ref f) const { } break; default: - f = Value(String(s, len[i])); + if(convert[i]) + f = Value(ToCharset(CHARSET_DEFAULT, String(s, len[i]), CHARSET_UTF8)); + else + f = Value(String(s, len[i])); break; } } diff --git a/uppsrc/Sql/ExportSch.cpp b/uppsrc/Sql/ExportSch.cpp index dd7bcf17c..f2fc4a0c1 100644 --- a/uppsrc/Sql/ExportSch.cpp +++ b/uppsrc/Sql/ExportSch.cpp @@ -47,7 +47,7 @@ String ExportSch(SqlSession& session, const String& database) break; } r << '\t' << sPutId(type, id, c[i].name, 8); - if(width > 0 && width < 4000) + if(width > 0 && width < 40000) r << ", " << width; r << ")\r\n"; } @@ -61,4 +61,35 @@ String ExportSch(const String& database) return ExportSch(SQL.GetSession(), database); } +static void sId(String& r, const String& id, Index& done) +{ + String u = ToUpper(id); + if(done.Find(u) >= 0) + return; + done.Add(u); + if(u == id) + r << "SQLID(" << id << ")\r\n"; + else + r << "SQL_ID(" << u << ", " << id << ")\r\n"; +} + +String ExportIds(SqlSession& session, const String& database) +{ + String r; + Vector tab = session.EnumTables(database); + Index done; + for(int i = 0; i < tab.GetCount(); i++) { + sId(r, tab[i], done); + Vector c = session.EnumColumns(database, tab[i]); + for(int i = 0; i < c.GetCount(); i++) + sId(r, c[i].name, done); + } + return r; +} + +String ExportIds(const String& database) +{ + return ExportIds(SQL.GetSession(), database); +} + END_UPP_NAMESPACE diff --git a/uppsrc/Sql/SqlSchema.h b/uppsrc/Sql/SqlSchema.h index d6a7316d1..12b5dbb6c 100644 --- a/uppsrc/Sql/SqlSchema.h +++ b/uppsrc/Sql/SqlSchema.h @@ -110,3 +110,5 @@ inline void SqlSchemaClear(T *a, int n) { String ExportSch(SqlSession& session, const String& database); String ExportSch(const String& database); +String ExportIds(SqlSession& session, const String& database); +String ExportIds(const String& database); diff --git a/uppsrc/Sql/Sqlexp.h b/uppsrc/Sql/Sqlexp.h index df689a369..ef33ff50b 100644 --- a/uppsrc/Sql/Sqlexp.h +++ b/uppsrc/Sql/Sqlexp.h @@ -109,13 +109,14 @@ public: SqlId operator [] (int i) const; SqlId operator&(const SqlId& s) const; - SqlId() {} - SqlId(const char *s) : id(s) {} - SqlId(const String& s) : id(s) {} - SqlId(Id id) : id(id) {} + SqlId() {} + SqlId(const char *s) : id(s) {} + SqlId(const String& s) : id(s) {} + SqlId(Id id) : id(id) {} }; -#define SQLID(x) const UPP::SqlId x(#x); +#define SQLID(x) const UPP::SqlId x(#x); +#define SQL_ID(n, x) const UPP::SqlId n(#x); class SqlS : Moveable { protected: