Added SQL_SetCharset native to (re)set character set (bug 5999, r=ds).

This commit is contained in:
Arkshine 2014-04-18 22:04:32 +02:00
parent 19e160117f
commit 3d732bbbb6
12 changed files with 94 additions and 1 deletions

View File

@ -16,6 +16,7 @@ void FreeConnection(void *p, unsigned int num)
free(cn->user); free(cn->user);
free(cn->pass); free(cn->pass);
free(cn->db); free(cn->db);
free(cn->charset);
delete cn; delete cn;
} }
@ -59,6 +60,7 @@ static cell AMX_NATIVE_CALL SQL_MakeDbTuple(AMX *amx, cell *params)
{ {
sql->max_timeout = static_cast<unsigned int>(params[5]); sql->max_timeout = static_cast<unsigned int>(params[5]);
} }
sql->charset = NULL;
unsigned int num = MakeHandle(sql, Handle_Connection, FreeConnection); unsigned int num = MakeHandle(sql, Handle_Connection, FreeConnection);
@ -92,6 +94,7 @@ static cell AMX_NATIVE_CALL SQL_Connect(AMX *amx, cell *params)
nfo.port = sql->port; nfo.port = sql->port;
nfo.host = sql->host; nfo.host = sql->host;
nfo.max_timeout = sql->max_timeout; nfo.max_timeout = sql->max_timeout;
nfo.charset = sql->charset;
char buffer[512]; char buffer[512];
int errcode; int errcode;
@ -585,6 +588,37 @@ static cell AMX_NATIVE_CALL SQL_QuoteStringFmt(AMX *amx, cell *params)
} }
} }
static cell AMX_NATIVE_CALL SQL_SetCharset(AMX *amx, cell *params)
{
SQL_Connection *sql = (SQL_Connection *)GetHandle(params[1], Handle_Connection);
if (!sql)
{
IDatabase *pDb = (IDatabase *)GetHandle(params[1], Handle_Database);
if (!pDb)
{
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid info tuple or database handle: %d", params[1]);
return 0;
}
int len;
return pDb->SetCharacterSet(MF_GetAmxString(amx, params[2], 0, &len));
}
else
{
int len;
const char *charset = MF_GetAmxString(amx, params[2], 0, &len);
if (!sql->charset || stricmp(charset, sql->charset))
{
sql->charset = strdup(charset);
}
return 1;
}
return 0;
}
AMX_NATIVE_INFO g_BaseSqlNatives[] = AMX_NATIVE_INFO g_BaseSqlNatives[] =
{ {
{"SQL_MakeDbTuple", SQL_MakeDbTuple}, {"SQL_MakeDbTuple", SQL_MakeDbTuple},
@ -610,6 +644,7 @@ AMX_NATIVE_INFO g_BaseSqlNatives[] =
{"SQL_QuoteString", SQL_QuoteString}, {"SQL_QuoteString", SQL_QuoteString},
{"SQL_QuoteStringFmt", SQL_QuoteStringFmt}, {"SQL_QuoteStringFmt", SQL_QuoteStringFmt},
{"SQL_NextResultSet", SQL_NextResultSet}, {"SQL_NextResultSet", SQL_NextResultSet},
{"SQL_SetCharset", SQL_SetCharset},
{NULL, NULL}, {NULL, NULL},
}; };

View File

@ -138,6 +138,13 @@ namespace SourceMod
* on internal failure. * on internal failure.
*/ */
virtual int QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newsize) =0; virtual int QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newsize) =0;
/**
* @brief Sets the character set of the current connection
*
* @param characterset The characterset to switch to. e.g. "utf8".
*/
virtual bool SetCharacterSet(const char *characterset) =0;
}; };
struct DatabaseInfo struct DatabaseInfo
@ -149,6 +156,7 @@ namespace SourceMod
const char *pass; const char *pass;
unsigned int port; unsigned int port;
unsigned int max_timeout; unsigned int max_timeout;
const char *charset;
}; };
class ISQLDriver class ISQLDriver

View File

@ -83,4 +83,7 @@ int MysqlDatabase::QuoteString(const char *str, char buffer[], size_t maxlen, si
return 0; return 0;
} }
bool MysqlDatabase::SetCharacterSet(const char *characterset)
{
return mysql_set_character_set(m_pMysql, characterset) == 0 ? true : false;
}

View File

@ -22,6 +22,7 @@ namespace SourceMod
IQuery *PrepareQueryFmt(const char *fmt, va_list ap); IQuery *PrepareQueryFmt(const char *fmt, va_list ap);
IQuery *PrepareQuery(const char *query); IQuery *PrepareQuery(const char *query);
int QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newsize); int QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newsize);
bool SetCharacterSet(const char *characterset);
private: private:
void Disconnect(); void Disconnect();
private: private:

View File

@ -72,6 +72,11 @@ IDatabase *MysqlDriver::_Connect(DatabaseInfo *info, int *errcode, char *error,
MysqlDatabase *pMysql = new MysqlDatabase(mysql, this); MysqlDatabase *pMysql = new MysqlDatabase(mysql, this);
if (info->charset && *info->charset)
{
pMysql->SetCharacterSet(info->charset);
}
return static_cast<IDatabase *>(pMysql); return static_cast<IDatabase *>(pMysql);
} }

View File

@ -35,6 +35,7 @@ struct SQL_Connection
char *db; char *db;
int port; int port;
unsigned int max_timeout; unsigned int max_timeout;
char *charset;
}; };
typedef void (*FREEHANDLE)(void *, unsigned int); typedef void (*FREEHANDLE)(void *, unsigned int);

View File

@ -82,6 +82,7 @@ static cell AMX_NATIVE_CALL SQL_ThreadQuery(AMX *amx, cell *params)
kmThread->SetForward(fwd); kmThread->SetForward(fwd);
kmThread->SetQuery(MF_GetAmxString(amx, params[3], 1, &len)); kmThread->SetQuery(MF_GetAmxString(amx, params[3], 1, &len));
kmThread->SetCellData(MF_GetAmxAddr(amx, params[4]), (ucell)params[5]); kmThread->SetCellData(MF_GetAmxAddr(amx, params[4]), (ucell)params[5]);
kmThread->SetCharacterSet(cn->charset);
g_pWorker->MakeThread(kmThread); g_pWorker->MakeThread(kmThread);
@ -139,6 +140,11 @@ void MysqlThread::SetInfo(const char *host, const char *user, const char *pass,
m_qrInfo.queue_time = gpGlobals->time; m_qrInfo.queue_time = gpGlobals->time;
} }
void MysqlThread::SetCharacterSet(const char *charset)
{
m_charset.assign(charset);
}
void MysqlThread::SetQuery(const char *query) void MysqlThread::SetQuery(const char *query)
{ {
m_query.assign(query); m_query.assign(query);
@ -154,6 +160,7 @@ void MysqlThread::RunThread(IThreadHandle *pHandle)
info.host = m_host.c_str(); info.host = m_host.c_str();
info.port = m_port; info.port = m_port;
info.max_timeout = m_max_timeout; info.max_timeout = m_max_timeout;
info.charset = m_charset.c_str();
float save_time = m_qrInfo.queue_time; float save_time = m_qrInfo.queue_time;

View File

@ -63,6 +63,7 @@ public:
~MysqlThread(); ~MysqlThread();
public: public:
void SetInfo(const char *host, const char *user, const char *pass, const char *db, int port, unsigned int max_timeout); void SetInfo(const char *host, const char *user, const char *pass, const char *db, int port, unsigned int max_timeout);
void SetCharacterSet(const char *charset);
void SetQuery(const char *query); void SetQuery(const char *query);
void SetCellData(cell data[], ucell len); void SetCellData(cell data[], ucell len);
void SetForward(int forward); void SetForward(int forward);
@ -78,6 +79,7 @@ private:
SourceHook::String m_pass; SourceHook::String m_pass;
SourceHook::String m_db; SourceHook::String m_db;
unsigned int m_max_timeout; unsigned int m_max_timeout;
SourceHook::String m_charset;
int m_port; int m_port;
cell *m_data; cell *m_data;
ucell m_datalen; ucell m_datalen;

View File

@ -137,6 +137,13 @@ namespace SourceMod
* on internal failure. * on internal failure.
*/ */
virtual int QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newsize) =0; virtual int QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newsize) =0;
/**
* @brief Sets the character set of the current connection
*
* @param characterset The characterset to switch to. e.g. "utf8".
*/
virtual bool SetCharacterSet(const char *characterset) =0;
}; };
struct DatabaseInfo struct DatabaseInfo
@ -148,6 +155,7 @@ namespace SourceMod
const char *pass; const char *pass;
unsigned int port; unsigned int port;
unsigned int max_timeout; unsigned int max_timeout;
const char *charset;
}; };
class ISQLDriver class ISQLDriver

View File

@ -78,3 +78,9 @@ int SqliteDatabase::QuoteString(const char *str, char buffer[], size_t maxlen, s
return 0; return 0;
} }
bool SqDatabase::SetCharacterSet(const char *characterset)
{
// sqlite only supports utf8 and utf16 - by the time the database is created. It's too late here.
return false;
}

View File

@ -22,6 +22,7 @@ namespace SourceMod
IQuery *PrepareQueryFmt(const char *fmt, va_list ap); IQuery *PrepareQueryFmt(const char *fmt, va_list ap);
IQuery *PrepareQuery(const char *query); IQuery *PrepareQuery(const char *query);
int QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newsize); int QuoteString(const char *str, char buffer[], size_t maxlen, size_t *newsize);
bool SqDatabase::SetCharacterSet(const char *characterset);
private: private:
void Disconnect(); void Disconnect();
private: private:

View File

@ -54,6 +54,22 @@ native SQL_FreeHandle(Handle:h);
native Handle:SQL_Connect(Handle:cn_tuple, &errcode, error[], maxlength); native Handle:SQL_Connect(Handle:cn_tuple, &errcode, error[], maxlength);
/**
* Sets the character set of the current connection.
* Like SET NAMES .. in mysql, but stays after connection problems.
*
* If a connection tuple is supplied, this should be called before SQL_Connect or SQL_ThreadQuery.
* Also note the change will remain until you call this function with another value.
*
* Example: "utf8", "latin1"
*
* @param h Database or connection tuple Handle.
* @param charset The character set string to change to.
* @return True, if character set was changed, false otherwise.
*/
native bool:SQL_SetCharset(Handle:h, const charset[]);
/** /**
* Prepares a query. * Prepares a query.
* The query must always be freed. * The query must always be freed.