msvc2010 fix
rename win_mysql -> sv_sql make mysql calls os independent git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3702 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
1067f351f2
commit
cc4f8982da
7 changed files with 958 additions and 1052 deletions
|
@ -265,6 +265,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#undef HLSERVER
|
||||
#undef WEBSERVER
|
||||
#undef VM_Q1
|
||||
#undef SQL
|
||||
#endif
|
||||
|
||||
//remove any options that depend upon GL.
|
||||
|
|
|
@ -1,14 +1,6 @@
|
|||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#define EMSGSIZE WSAEMSGSIZE
|
||||
#define ECONNRESET WSAECONNRESET
|
||||
#define ECONNABORTED WSAECONNABORTED
|
||||
#define ECONNREFUSED WSAECONNREFUSED
|
||||
#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
|
||||
#define EAFNOSUPPORT WSAEAFNOSUPPORT
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define USEIPX
|
||||
#endif
|
||||
|
@ -17,6 +9,7 @@
|
|||
#include "wsipx.h"
|
||||
#endif
|
||||
#include <ws2tcpip.h>
|
||||
#include <errno.h>
|
||||
#ifndef IPPROTO_IPV6
|
||||
/*for msvc6*/
|
||||
#define IPPROTO_IPV6
|
||||
|
@ -69,6 +62,24 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if (_MSC_VER >= 1600)
|
||||
#undef EADDRNOTAVAIL
|
||||
#undef EAFNOSUPPORT
|
||||
#undef ECONNABORTED
|
||||
#undef ECONNREFUSED
|
||||
#undef ECONNRESET
|
||||
#undef EMSGSIZE
|
||||
#undef EWOULDBLOCK
|
||||
#endif
|
||||
|
||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#define EMSGSIZE WSAEMSGSIZE
|
||||
#define ECONNRESET WSAECONNRESET
|
||||
#define ECONNABORTED WSAECONNABORTED
|
||||
#define ECONNREFUSED WSAECONNREFUSED
|
||||
#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
|
||||
#define EAFNOSUPPORT WSAEAFNOSUPPORT
|
||||
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
|
File diff suppressed because it is too large
Load diff
813
engine/server/sv_sql.c
Normal file
813
engine/server/sv_sql.c
Normal file
|
@ -0,0 +1,813 @@
|
|||
#include "quakedef.h"
|
||||
|
||||
#ifdef SQL
|
||||
#include "sv_sql.h"
|
||||
|
||||
static void (VARGS *qmysql_library_end)(void);
|
||||
static int (VARGS *qmysql_library_init)(int argc, char **argv, char **groups);
|
||||
|
||||
static my_ulonglong (VARGS *qmysql_affected_rows)(MYSQL *mysql);
|
||||
static void (VARGS *qmysql_close)(MYSQL *sock);
|
||||
static void (VARGS *qmysql_data_seek)(MYSQL_RES *result, my_ulonglong offset);
|
||||
static unsigned int (VARGS *qmysql_errno)(MYSQL *mysql);
|
||||
static const char *(VARGS *qmysql_error)(MYSQL *mysql);
|
||||
static MYSQL_FIELD *(VARGS *qmysql_fetch_field_direct)(MYSQL_RES *res, unsigned int fieldnr);
|
||||
static MYSQL_ROW (VARGS *qmysql_fetch_row)(MYSQL_RES *result);
|
||||
static unsigned int (VARGS *qmysql_field_count)(MYSQL *mysql);
|
||||
static void (VARGS *qmysql_free_result)(MYSQL_RES *result);
|
||||
static const char *(VARGS *qmysql_get_client_info)(void);
|
||||
static MYSQL *(VARGS *qmysql_init)(MYSQL *mysql);
|
||||
static MYSQL_RES *(VARGS *qmysql_store_result)(MYSQL *mysql);
|
||||
static unsigned int (VARGS *qmysql_num_fields)(MYSQL_RES *res);
|
||||
static my_ulonglong (VARGS *qmysql_num_rows)(MYSQL_RES *res);
|
||||
static int (VARGS *qmysql_options)(MYSQL *mysql, enum mysql_option option, const char *arg);
|
||||
static int (VARGS *qmysql_query)(MYSQL *mysql, const char *q);
|
||||
static MYSQL *(VARGS *qmysql_real_connect)(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long clientflag);
|
||||
static unsigned long (VARGS *qmysql_real_escape_string)(MYSQL *mysql, char *to, const char *from, unsigned long length);
|
||||
static void (VARGS *qmysql_thread_end)(void);
|
||||
static my_bool (VARGS *qmysql_thread_init)(void);
|
||||
static unsigned int (VARGS *qmysql_thread_safe)(void);
|
||||
|
||||
static dllfunction_t mysqlfuncs[] =
|
||||
{
|
||||
{(void*)&qmysql_library_end, "mysql_server_end"}, /* written as a define alias in mysql.h */
|
||||
{(void*)&qmysql_library_init, "mysql_server_init"}, /* written as a define alias in mysql.h */
|
||||
{(void*)&qmysql_affected_rows, "mysql_affected_rows"},
|
||||
{(void*)&qmysql_close, "mysql_close"},
|
||||
{(void*)&qmysql_data_seek, "mysql_data_seek"},
|
||||
{(void*)&qmysql_errno, "mysql_errno"},
|
||||
{(void*)&qmysql_error, "mysql_error"},
|
||||
{(void*)&qmysql_fetch_field_direct, "mysql_fetch_field_direct"},
|
||||
{(void*)&qmysql_fetch_row, "mysql_fetch_row"},
|
||||
{(void*)&qmysql_field_count, "mysql_field_count"},
|
||||
{(void*)&qmysql_free_result, "mysql_free_result"},
|
||||
{(void*)&qmysql_get_client_info, "mysql_get_client_info"},
|
||||
{(void*)&qmysql_init, "mysql_init"},
|
||||
{(void*)&qmysql_store_result, "mysql_store_result"},
|
||||
{(void*)&qmysql_num_fields, "mysql_num_fields"},
|
||||
{(void*)&qmysql_num_rows, "mysql_num_rows"},
|
||||
{(void*)&qmysql_options, "mysql_options"},
|
||||
{(void*)&qmysql_query, "mysql_query"},
|
||||
{(void*)&qmysql_real_connect, "mysql_real_connect"},
|
||||
{(void*)&qmysql_real_escape_string, "mysql_real_escape_string"},
|
||||
{(void*)&qmysql_thread_end, "mysql_thread_end"},
|
||||
{(void*)&qmysql_thread_init, "mysql_thread_init"},
|
||||
{(void*)&qmysql_thread_safe, "mysql_thread_safe"},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
cvar_t sql_driver = SCVARF("sv_sql_driver", "mysql", CVAR_NOUNSAFEEXPAND);
|
||||
cvar_t sql_host = SCVARF("sv_sql_host", "127.0.0.1", CVAR_NOUNSAFEEXPAND);
|
||||
cvar_t sql_username = SCVARF("sv_sql_username", "", CVAR_NOUNSAFEEXPAND);
|
||||
cvar_t sql_password = SCVARF("sv_sql_password", "", CVAR_NOUNSAFEEXPAND);
|
||||
cvar_t sql_defaultdb = SCVARF("sv_sql_defaultdb", "", CVAR_NOUNSAFEEXPAND);
|
||||
|
||||
void SQL_PushResult(sqlserver_t *server, queryresult_t *qres)
|
||||
{
|
||||
Sys_LockMutex(server->resultlock);
|
||||
qres->next = NULL;
|
||||
if (!server->resultslast)
|
||||
server->results = server->resultslast = qres;
|
||||
else
|
||||
server->resultslast = server->resultslast->next = qres;
|
||||
Sys_UnlockMutex(server->resultlock);
|
||||
}
|
||||
|
||||
queryresult_t *SQL_PullResult(sqlserver_t *server)
|
||||
{
|
||||
queryresult_t *qres;
|
||||
Sys_LockMutex(server->resultlock);
|
||||
qres = server->results;
|
||||
if (qres)
|
||||
{
|
||||
server->results = qres->next;
|
||||
if (!server->results)
|
||||
server->resultslast = NULL;
|
||||
}
|
||||
Sys_UnlockMutex(server->resultlock);
|
||||
|
||||
return qres;
|
||||
}
|
||||
|
||||
void SQL_PushRequest(sqlserver_t *server, queryrequest_t *qreq)
|
||||
{
|
||||
Sys_LockConditional(server->requestcondv);
|
||||
qreq->next = NULL;
|
||||
if (!server->requestslast)
|
||||
server->requests = server->requestslast = qreq;
|
||||
else
|
||||
server->requestslast = server->requestslast->next = qreq;
|
||||
Sys_UnlockConditional(server->requestcondv);
|
||||
}
|
||||
|
||||
queryrequest_t *SQL_PullRequest(sqlserver_t *server, qboolean lock)
|
||||
{
|
||||
queryrequest_t *qreq;
|
||||
if (lock)
|
||||
Sys_LockConditional(server->requestcondv);
|
||||
qreq = server->requests;
|
||||
if (qreq)
|
||||
{
|
||||
server->requests = qreq->next;
|
||||
if (!server->requests)
|
||||
server->requestslast = NULL;
|
||||
}
|
||||
Sys_UnlockConditional(server->requestcondv);
|
||||
|
||||
return qreq;
|
||||
}
|
||||
|
||||
sqlserver_t **sqlservers;
|
||||
int sqlservercount;
|
||||
qboolean sqlavailable;
|
||||
|
||||
int sql_serverworker(void *sref)
|
||||
{
|
||||
sqlserver_t *server = (sqlserver_t *)sref;
|
||||
char *error = NULL;
|
||||
my_bool reconnect = 1;
|
||||
int tinit, i;
|
||||
qboolean needlock = false;
|
||||
|
||||
if (tinit = qmysql_thread_init())
|
||||
error = "MYSQL thread init failed";
|
||||
else if (!(server->mysql = qmysql_init(NULL)))
|
||||
error = "MYSQL init failed";
|
||||
else if (qmysql_options(server->mysql, MYSQL_OPT_RECONNECT, &reconnect))
|
||||
error = "MYSQL reconnect options set failed";
|
||||
else
|
||||
{
|
||||
int port = 0;
|
||||
char *colon;
|
||||
|
||||
colon = strchr(server->connectparams[0], ':');
|
||||
if (colon)
|
||||
{
|
||||
*colon = '\0';
|
||||
port = atoi(colon + 1);
|
||||
}
|
||||
|
||||
if (!(server->mysql = qmysql_real_connect(server->mysql, server->connectparams[0], server->connectparams[1], server->connectparams[2], server->connectparams[3], port, 0, 0)))
|
||||
error = "MYSQL initial connect attempt failed";
|
||||
|
||||
if (colon)
|
||||
*colon = ':';
|
||||
}
|
||||
|
||||
for (i = SQL_CONNECT_STRUCTPARAMS; i < SQL_CONNECT_PARAMS; i++)
|
||||
Z_Free(server->connectparams[i]);
|
||||
|
||||
BZ_Realloc(server->connectparams, sizeof(char *) * SQL_CONNECT_STRUCTPARAMS);
|
||||
|
||||
if (error)
|
||||
server->active = false;
|
||||
|
||||
while (server->active)
|
||||
{
|
||||
Sys_LockConditional(server->requestcondv);
|
||||
if (!server->requests) // this is needed for thread startup and to catch any "lost" changes
|
||||
Sys_ConditionWait(server->requestcondv);
|
||||
needlock = false; // so we don't try to relock first round
|
||||
|
||||
while (1)
|
||||
{
|
||||
queryrequest_t *qreq = NULL;
|
||||
queryresult_t *qres;
|
||||
const char *qerror = NULL;
|
||||
MYSQL_RES *mysqlres = NULL;
|
||||
int rows = -1;
|
||||
int columns = -1;
|
||||
int qesize = 0;
|
||||
|
||||
if (!(qreq = SQL_PullRequest(server, needlock)))
|
||||
break;
|
||||
|
||||
// pullrequest makes sure our condition is unlocked but we'll need
|
||||
// a lock next round
|
||||
needlock = true;
|
||||
|
||||
// perform the query and fill out the result structure
|
||||
if (qmysql_query(server->mysql, qreq->query))
|
||||
qerror = qmysql_error(server->mysql);
|
||||
else // query succeeded
|
||||
{
|
||||
mysqlres = qmysql_store_result(server->mysql);
|
||||
if (mysqlres) // result set returned
|
||||
{
|
||||
rows = qmysql_num_rows(mysqlres);
|
||||
columns = qmysql_num_fields(mysqlres);
|
||||
}
|
||||
else if (qmysql_field_count(server->mysql) == 0) // no result set
|
||||
{
|
||||
rows = qmysql_affected_rows(server->mysql);
|
||||
if (rows < 0)
|
||||
rows = 0;
|
||||
columns = 0;
|
||||
}
|
||||
else // error
|
||||
qerror = qmysql_error(server->mysql);
|
||||
}
|
||||
|
||||
if (qerror)
|
||||
qesize = Q_strlen(qerror);
|
||||
qres = (queryresult_t *)ZF_Malloc(sizeof(queryresult_t) + qesize);
|
||||
if (qres)
|
||||
{
|
||||
if (qerror)
|
||||
Q_strncpy(qres->error, qerror, qesize);
|
||||
qres->result = mysqlres;
|
||||
qres->rows = rows;
|
||||
qres->columns = columns;
|
||||
qres->request = qreq;
|
||||
qres->eof = true; // store result has no more rows to read afterwards
|
||||
qreq->next = NULL;
|
||||
|
||||
SQL_PushResult(server, qres);
|
||||
}
|
||||
else // we're screwed here so bomb out
|
||||
{
|
||||
server->active = false;
|
||||
error = "MALLOC ERROR! Unable to allocate query result!";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (server->mysql)
|
||||
qmysql_close(server->mysql);
|
||||
|
||||
// if we have a server error we still need to put it on the queue
|
||||
if (error)
|
||||
{
|
||||
int esize = Q_strlen(error);
|
||||
queryresult_t *qres = (queryresult_t *)Z_Malloc(sizeof(queryresult_t) + esize);
|
||||
if (qres)
|
||||
{ // hopefully the qmysql_close gained us some memory otherwise we're pretty screwed
|
||||
qres->rows = qres->columns = -1;
|
||||
Q_strncpy(qres->error, error, esize);
|
||||
|
||||
SQL_PushResult(server, qres);
|
||||
}
|
||||
}
|
||||
|
||||
if (!tinit)
|
||||
qmysql_thread_end();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sqlserver_t *SQL_GetServer (int serveridx, qboolean inactives)
|
||||
{
|
||||
if (serveridx < 0 || serveridx >= sqlservercount)
|
||||
return NULL;
|
||||
if (!inactives && sqlservers[serveridx]->active == false)
|
||||
return NULL;
|
||||
return sqlservers[serveridx];
|
||||
}
|
||||
|
||||
queryresult_t *SQL_GetQueryResult (sqlserver_t *server, int queryidx)
|
||||
{
|
||||
queryresult_t *qres;
|
||||
|
||||
qres = server->currentresult;
|
||||
if (qres && qres->request && qres->request->num == queryidx)
|
||||
return qres;
|
||||
|
||||
for (qres = server->persistresults; qres; qres = qres->next)
|
||||
if (qres->request && qres->request->num == queryidx)
|
||||
return qres;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void SQL_DeallocResult(queryresult_t *qres)
|
||||
{
|
||||
// deallocate current result
|
||||
if (qres->result)
|
||||
qmysql_free_result(qres->result);
|
||||
if (qres->request)
|
||||
Z_Free(qres->request);
|
||||
|
||||
Z_Free(qres);
|
||||
}
|
||||
|
||||
void SQL_ClosePersistantResult(sqlserver_t *server, queryresult_t *qres)
|
||||
{
|
||||
queryresult_t *prev, *cur;
|
||||
|
||||
prev = server->persistresults;
|
||||
if (prev == qres)
|
||||
{
|
||||
server->persistresults = prev->next;
|
||||
SQL_DeallocResult(prev);
|
||||
return;
|
||||
}
|
||||
|
||||
for (cur = prev->next; cur; prev = cur, cur = prev->next)
|
||||
{
|
||||
if (cur == qres)
|
||||
{
|
||||
prev = cur->next;
|
||||
SQL_DeallocResult(cur);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SQL_CloseResult(sqlserver_t *server, queryresult_t *qres)
|
||||
{
|
||||
if (!qres)
|
||||
return;
|
||||
if (qres == server->currentresult)
|
||||
{
|
||||
SQL_DeallocResult(server->currentresult);
|
||||
server->currentresult = NULL;
|
||||
return;
|
||||
}
|
||||
// else we have a persistant query
|
||||
SQL_ClosePersistantResult(server, qres);
|
||||
}
|
||||
|
||||
void SQL_CloseAllResults(sqlserver_t *server)
|
||||
{
|
||||
queryresult_t *oldqres, *qres;
|
||||
|
||||
// close orphaned results (we assume the lock is active or non-existant at this point)
|
||||
qres = server->results;
|
||||
while (qres)
|
||||
{
|
||||
oldqres = qres;
|
||||
qres = qres->next;
|
||||
SQL_DeallocResult(oldqres);
|
||||
}
|
||||
// close current
|
||||
if (server->currentresult)
|
||||
{
|
||||
SQL_DeallocResult(server->currentresult);
|
||||
server->currentresult = NULL;
|
||||
}
|
||||
// close persistant results
|
||||
qres = server->persistresults;
|
||||
while (qres)
|
||||
{
|
||||
oldqres = qres;
|
||||
qres = qres->next;
|
||||
SQL_DeallocResult(oldqres);
|
||||
}
|
||||
server->persistresults = NULL;
|
||||
// close server result
|
||||
if (server->serverresult)
|
||||
{
|
||||
SQL_DeallocResult(server->serverresult);
|
||||
server->serverresult = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
char *SQL_ReadField (sqlserver_t *server, queryresult_t *qres, int row, int col, qboolean fields)
|
||||
{
|
||||
if (!qres->result) // TODO: partial resultset logic not implemented yet
|
||||
return NULL;
|
||||
else
|
||||
{ // store_result query
|
||||
if (qres->rows < row || qres->columns < col || col < 0)
|
||||
return NULL;
|
||||
|
||||
if (row < 0)
|
||||
{ // fetch field name
|
||||
if (fields) // but only if we asked for them
|
||||
{
|
||||
MYSQL_FIELD *field;
|
||||
|
||||
field = qmysql_fetch_field_direct(qres->result, col);
|
||||
|
||||
if (!field)
|
||||
return NULL;
|
||||
else
|
||||
return field->name;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{ // fetch data
|
||||
MYSQL_ROW sqlrow;
|
||||
|
||||
qmysql_data_seek(qres->result, row);
|
||||
sqlrow = qmysql_fetch_row(qres->result);
|
||||
if (!sqlrow || !sqlrow[col])
|
||||
return NULL;
|
||||
else
|
||||
return sqlrow[col];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int SQL_NewServer(char *driver, char **paramstr)
|
||||
{
|
||||
sqlserver_t *server;
|
||||
int serverref;
|
||||
int drvchoice;
|
||||
int paramsize[SQL_CONNECT_PARAMS];
|
||||
int i, tsize;
|
||||
|
||||
for (i = 0; i < SQL_CONNECT_PARAMS; i++)
|
||||
paramsize[i] = Q_strlen(paramstr[i]);
|
||||
|
||||
if (Q_strcasecmp(driver, "mysql") == 0)
|
||||
drvchoice = SQLDRV_MYSQL;
|
||||
else if (Q_strcasecmp(driver, "sqlite") == 0)
|
||||
return -1; // drvchoice = SQLDRV_SQLITE;
|
||||
else // invalid driver choice so we bomb out
|
||||
return -1;
|
||||
|
||||
// alloc or realloc sql servers array
|
||||
if (sqlservers == NULL)
|
||||
{
|
||||
serverref = 0;
|
||||
sqlservercount = 1;
|
||||
sqlservers = (sqlserver_t **)BZ_Malloc(sizeof(sqlserver_t *));
|
||||
}
|
||||
else
|
||||
{
|
||||
serverref = sqlservercount;
|
||||
sqlservercount++;
|
||||
sqlservers = (sqlserver_t **)BZ_Realloc(sqlservers, sizeof(sqlserver_t *) * sqlservercount);
|
||||
}
|
||||
|
||||
// assemble server structure
|
||||
tsize = 0;
|
||||
for (i = 0; i < SQL_CONNECT_STRUCTPARAMS; i++)
|
||||
tsize += paramsize[i] + 1; // allocate extra space for host and user only
|
||||
|
||||
server = (sqlserver_t *)Z_Malloc(sizeof(sqlserver_t) + tsize);
|
||||
server->connectparams = (char **)BZ_Malloc(sizeof(char *) * SQL_CONNECT_PARAMS);
|
||||
|
||||
tsize = 0;
|
||||
for (i = 0; i < SQL_CONNECT_STRUCTPARAMS; i++)
|
||||
{
|
||||
server->connectparams[i] = ((char *)(server + 1)) + tsize;
|
||||
Q_strncpy(server->connectparams[i], paramstr[i], paramsize[i]);
|
||||
// string should be null-terminated due to Z_Malloc
|
||||
tsize += paramsize[i] + 1;
|
||||
}
|
||||
for (i = SQL_CONNECT_STRUCTPARAMS; i < SQL_CONNECT_PARAMS; i++)
|
||||
{
|
||||
server->connectparams[i] = (char *)Z_Malloc(sizeof(char) * (paramsize[i] + 1));
|
||||
Q_strncpy(server->connectparams[i], paramstr[i], paramsize[i]);
|
||||
// string should be null-terminated due to Z_Malloc
|
||||
}
|
||||
|
||||
sqlservers[serverref] = server;
|
||||
|
||||
server->driver = (sqldrv_t)drvchoice;
|
||||
server->querynum = 1;
|
||||
server->active = true;
|
||||
server->requestcondv = Sys_CreateConditional();
|
||||
server->resultlock = Sys_CreateMutex();
|
||||
|
||||
if (!server->requestcondv || !server->resultlock)
|
||||
{
|
||||
if (server->requestcondv)
|
||||
Sys_DestroyConditional(server->requestcondv);
|
||||
if (server->resultlock)
|
||||
Sys_DestroyMutex(server->resultlock);
|
||||
Z_Free(server);
|
||||
sqlservercount--;
|
||||
return -1;
|
||||
}
|
||||
|
||||
server->thread = Sys_CreateThread(sql_serverworker, (void *)server, 1024);
|
||||
|
||||
if (!server->thread)
|
||||
{
|
||||
Z_Free(server);
|
||||
sqlservercount--;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return serverref;
|
||||
}
|
||||
|
||||
int SQL_NewQuery(sqlserver_t *server, int callfunc, int type, int self, float selfid, int other, float otherid, char *str)
|
||||
{
|
||||
int qsize = Q_strlen(str);
|
||||
queryrequest_t *qreq;
|
||||
int querynum;
|
||||
|
||||
qreq = (queryrequest_t *)ZF_Malloc(sizeof(queryrequest_t) + qsize);
|
||||
if (qreq)
|
||||
{
|
||||
qreq->persistant = (type == 1);
|
||||
qreq->callback = callfunc;
|
||||
|
||||
qreq->selfent = self;
|
||||
qreq->selfid = selfid;
|
||||
qreq->otherent = other;
|
||||
qreq->otherid = otherid;
|
||||
|
||||
querynum = qreq->num = server->querynum;
|
||||
// prevent the reference num from getting too big to prevent FP problems
|
||||
if (++server->querynum > 1000000)
|
||||
server->querynum = 1;
|
||||
|
||||
Q_strncpy(qreq->query, str, qsize);
|
||||
|
||||
SQL_PushRequest(server, qreq);
|
||||
Sys_ConditionSignal(server->requestcondv);
|
||||
|
||||
return querynum;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void SQL_Disconnect(sqlserver_t *server)
|
||||
{
|
||||
server->active = false;
|
||||
|
||||
// force the threads to reiterate requests and hopefully terminate
|
||||
Sys_ConditionBroadcast(server->requestcondv);
|
||||
}
|
||||
|
||||
void SQL_Escape(sqlserver_t *server, char *src, char *dst, int dstlen)
|
||||
{
|
||||
int srclen;
|
||||
|
||||
switch (server->driver)
|
||||
{
|
||||
case SQLDRV_MYSQL:
|
||||
srclen = strlen(dst);
|
||||
if (srclen > (dstlen / 2 - 1))
|
||||
dst[0] = '\0';
|
||||
qmysql_real_escape_string(server->mysql, dst, src, srclen);
|
||||
break;
|
||||
default:
|
||||
dst[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
char *SQL_Info(sqlserver_t *server)
|
||||
{
|
||||
switch (server->driver)
|
||||
{
|
||||
case SQLDRV_MYSQL:
|
||||
return va("mysql: %s", qmysql_get_client_info());
|
||||
break;
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
qboolean SQL_Available(void)
|
||||
{
|
||||
return sqlavailable;
|
||||
}
|
||||
|
||||
/* SQL related commands */
|
||||
void SQL_Status_f(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
Con_Printf("%i connections\n", sqlservercount);
|
||||
for (i = 0; i < sqlservercount; i++)
|
||||
{
|
||||
int reqnum = 0;
|
||||
int resnum = 0;
|
||||
queryrequest_t *qreq;
|
||||
queryresult_t *qres;
|
||||
|
||||
sqlserver_t *server = sqlservers[i];
|
||||
|
||||
Sys_LockMutex(server->resultlock);
|
||||
Sys_LockConditional(server->requestcondv);
|
||||
for (qreq = server->requests; qreq; qreq = qreq->next)
|
||||
reqnum++;
|
||||
for (qres = server->results; qres; qres = qres->next)
|
||||
resnum++;
|
||||
|
||||
Con_Printf("#%i %s@%s: %s\n",
|
||||
i,
|
||||
server->connectparams[1],
|
||||
server->connectparams[0],
|
||||
server->active ? "active" : "inactive");
|
||||
|
||||
if (reqnum)
|
||||
{
|
||||
Con_Printf ("- %i requests\n");
|
||||
for (qreq = server->requests; qreq; qreq = qreq->next)
|
||||
{
|
||||
Con_Printf (" query #%i: %s\n",
|
||||
qreq->num,
|
||||
qreq->query);
|
||||
// TODO: function lookup?
|
||||
}
|
||||
}
|
||||
|
||||
if (resnum)
|
||||
{
|
||||
Con_Printf ("- %i results\n");
|
||||
for (qres = server->results; qres; qres = qres->next)
|
||||
{
|
||||
Con_Printf (" * %i rows, %i columns",
|
||||
qres->rows,
|
||||
qres->columns);
|
||||
if (qres->error[0])
|
||||
Con_Printf(", error %s\n", qres->error);
|
||||
else
|
||||
Con_Printf("\n");
|
||||
// TODO: request info?
|
||||
}
|
||||
}
|
||||
|
||||
if (server->serverresult)
|
||||
Con_Printf ("server result: error %s\n", server->serverresult->error);
|
||||
|
||||
// TODO: list all requests, results here
|
||||
Sys_UnlockMutex(server->resultlock);
|
||||
Sys_UnlockConditional(server->requestcondv);
|
||||
}
|
||||
}
|
||||
|
||||
void SQL_Kill_f (void)
|
||||
{
|
||||
sqlserver_t *server;
|
||||
|
||||
if (Cmd_Argc() < 2)
|
||||
{
|
||||
Con_Printf ("Syntax: %s serverid\n", Cmd_Argv(0));
|
||||
return;
|
||||
}
|
||||
|
||||
server = SQL_GetServer(atoi(Cmd_Argv(1)), false);
|
||||
if (server)
|
||||
{
|
||||
server->active = false;
|
||||
Sys_ConditionBroadcast(server->requestcondv);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void SQL_Killall_f (void)
|
||||
{
|
||||
SQL_KillServers();
|
||||
}
|
||||
|
||||
void SQL_ServerCycle (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sqlservercount; i++)
|
||||
{
|
||||
sqlserver_t *server = sqlservers[i];
|
||||
queryresult_t *qres;
|
||||
|
||||
while (qres = SQL_PullResult(server))
|
||||
{
|
||||
qres->next = NULL;
|
||||
if (qres->request && qres->request->callback)
|
||||
{
|
||||
if (server->active)
|
||||
{ // only process results to callback if server is active
|
||||
edict_t *ent;
|
||||
|
||||
server->currentresult = qres;
|
||||
G_FLOAT(OFS_PARM0) = i;
|
||||
G_FLOAT(OFS_PARM1) = qres->request->num;
|
||||
G_FLOAT(OFS_PARM2) = qres->rows;
|
||||
G_FLOAT(OFS_PARM3) = qres->columns;
|
||||
G_FLOAT(OFS_PARM4) = qres->eof;
|
||||
|
||||
// recall self and other references
|
||||
ent = PROG_TO_EDICT(prinst, qres->request->selfent);
|
||||
if (ent->isfree || ent->xv->uniquespawnid != qres->request->selfid)
|
||||
pr_global_struct->self = pr_global_struct->world;
|
||||
else
|
||||
pr_global_struct->self = qres->request->selfent;
|
||||
ent = PROG_TO_EDICT(prinst, qres->request->otherent);
|
||||
if (ent->isfree || ent->xv->uniquespawnid != qres->request->otherid)
|
||||
pr_global_struct->other = pr_global_struct->world;
|
||||
else
|
||||
pr_global_struct->other = qres->request->otherent;
|
||||
|
||||
PR_ExecuteProgram(prinst, qres->request->callback);
|
||||
|
||||
if (qres->eof)
|
||||
{
|
||||
if (server->currentresult)
|
||||
{
|
||||
if (server->currentresult->request && server->currentresult->request->persistant)
|
||||
{
|
||||
// move into persistant list
|
||||
server->currentresult->next = server->persistresults;
|
||||
server->persistresults = server->currentresult;
|
||||
}
|
||||
else // just close the query
|
||||
SQL_CloseResult(server, server->currentresult);
|
||||
}
|
||||
}
|
||||
// TODO: else we move a request back into the queue?
|
||||
}
|
||||
}
|
||||
else // error or server-only result
|
||||
{
|
||||
if (server->serverresult)
|
||||
Z_Free(server->serverresult);
|
||||
server->serverresult = qres;
|
||||
}
|
||||
}
|
||||
server->currentresult = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void SQL_MYSQLInit(void)
|
||||
{
|
||||
if (!(mysqlhandle = Sys_LoadLibrary("libmysql", mysqlfuncs)))
|
||||
{
|
||||
Con_Printf("mysql client didn't load\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (qmysql_thread_safe())
|
||||
{
|
||||
if (!qmysql_library_init(0, NULL, NULL))
|
||||
{
|
||||
Con_Printf("MYSQL backend loaded\n");
|
||||
sqlavailable = true;
|
||||
return;
|
||||
}
|
||||
else
|
||||
Con_Printf("MYSQL library init failed!\n");
|
||||
}
|
||||
else
|
||||
Con_Printf("MYSQL client is not thread safe!\n");
|
||||
|
||||
Sys_CloseLibrary(mysqlhandle);
|
||||
sqlavailable = false;
|
||||
}
|
||||
|
||||
void SQL_Init(void)
|
||||
{
|
||||
Cmd_AddCommand ("sqlstatus", SQL_Status_f);
|
||||
Cmd_AddCommand ("sqlkill", SQL_Kill_f);
|
||||
Cmd_AddCommand ("sqlkillall", SQL_Killall_f);
|
||||
|
||||
Cvar_Register(&sql_driver, SQLCVAROPTIONS);
|
||||
Cvar_Register(&sql_host, SQLCVAROPTIONS);
|
||||
Cvar_Register(&sql_username, SQLCVAROPTIONS);
|
||||
Cvar_Register(&sql_password, SQLCVAROPTIONS);
|
||||
Cvar_Register(&sql_defaultdb, SQLCVAROPTIONS);
|
||||
|
||||
SQL_MYSQLInit();
|
||||
}
|
||||
|
||||
void SQL_KillServers(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < sqlservercount; i++)
|
||||
{
|
||||
sqlserver_t *server = sqlservers[i];
|
||||
queryrequest_t *qreq, *oldqreq;
|
||||
|
||||
server->active = false; // set thread to kill itself
|
||||
Sys_ConditionBroadcast(server->requestcondv); // force condition check
|
||||
Sys_WaitOnThread(server->thread); // wait on thread to die
|
||||
|
||||
// server resource deallocation (TODO: should this be done in the thread itself?)
|
||||
Sys_DestroyConditional(server->requestcondv);
|
||||
Sys_DestroyMutex(server->resultlock);
|
||||
|
||||
// close orphaned requests
|
||||
qreq = server->requests;
|
||||
while (qreq)
|
||||
{
|
||||
oldqreq = qreq;
|
||||
qreq = qreq->next;
|
||||
Z_Free(oldqreq);
|
||||
}
|
||||
|
||||
SQL_CloseAllResults(server);
|
||||
|
||||
// the alloc'ed connect params should get deallocated by the thread
|
||||
if (server->connectparams)
|
||||
BZ_Free(server->connectparams);
|
||||
|
||||
Z_Free(server);
|
||||
}
|
||||
if (sqlservers)
|
||||
Z_Free(sqlservers);
|
||||
sqlservers = NULL;
|
||||
sqlservercount = 0;
|
||||
}
|
||||
|
||||
void SQL_DeInit(void)
|
||||
{
|
||||
sqlavailable = false;
|
||||
|
||||
SQL_KillServers();
|
||||
|
||||
qmysql_library_end();
|
||||
|
||||
Sys_CloseLibrary(mysqlhandle);
|
||||
}
|
||||
|
||||
#endif
|
91
engine/server/sv_sql.h
Normal file
91
engine/server/sv_sql.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
#ifndef MYSQLDLL_H
|
||||
#define MYSQLDLL_H
|
||||
#include <mysql/mysql.h>
|
||||
|
||||
dllhandle_t *mysqlhandle;
|
||||
|
||||
#define SQL_CONNECT_STRUCTPARAMS 2
|
||||
#define SQL_CONNECT_PARAMS 4
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SQLDRV_MYSQL,
|
||||
SQLDRV_SQLITE, /* NOT IN YET */
|
||||
SQLDRV_INVALID
|
||||
} sqldrv_t;
|
||||
|
||||
typedef struct queryrequest_s
|
||||
{
|
||||
int num; /* query number reference */
|
||||
qboolean persistant; /* persistant query */
|
||||
struct queryrequest_s *next; /* next request in queue */
|
||||
int callback; /* callback function reference */
|
||||
int selfent; /* self entity on call */
|
||||
float selfid; /* self entity id on call */
|
||||
int otherent; /* other entity on call */
|
||||
float otherid; /* other entity id on call */
|
||||
char query[1]; /* query to run */
|
||||
} queryrequest_t;
|
||||
|
||||
typedef struct queryresult_s
|
||||
{
|
||||
struct queryrequest_s *request; /* corresponding request */
|
||||
struct queryresult_s *next; /* next result in queue */
|
||||
int rows; /* rows contained in single result set */
|
||||
int columns; /* fields */
|
||||
qboolean eof; /* end of query reached */
|
||||
MYSQL_RES *result; /* result set from mysql */
|
||||
#if 0
|
||||
char **resultset; /* stored result set from partial fetch */
|
||||
#endif
|
||||
char error[1]; /* error string, "" if none */
|
||||
} queryresult_t;
|
||||
|
||||
typedef struct sqlserver_s
|
||||
{
|
||||
void *thread; /* worker thread for server */
|
||||
sqldrv_t driver; /* driver type */
|
||||
MYSQL *mysql; /* mysql server */
|
||||
volatile qboolean active; /* set to false to kill thread */
|
||||
void *requestcondv; /* lock and conditional variable for queue read/write */
|
||||
void *resultlock; /* mutex for queue read/write */
|
||||
int querynum; /* next reference number for queries */
|
||||
queryrequest_t *requests; /* query requests queue */
|
||||
queryrequest_t *requestslast; /* query requests queue last link */
|
||||
queryresult_t *results; /* query results queue */
|
||||
queryresult_t *resultslast; /* query results queue last link */
|
||||
queryresult_t *currentresult; /* current called result */
|
||||
queryresult_t *persistresults; /* list of persistant results */
|
||||
queryresult_t *serverresult; /* server error results */
|
||||
char **connectparams; /* connect parameters (0 = host, 1 = user, 2 = pass, 3 = defaultdb) */
|
||||
} sqlserver_t;
|
||||
|
||||
/* prototypes */
|
||||
void SQL_Init(void);
|
||||
void SQL_KillServers(void);
|
||||
void SQL_DeInit(void);
|
||||
|
||||
sqlserver_t *SQL_GetServer (int serveridx, qboolean inactives);
|
||||
queryresult_t *SQL_GetQueryResult (sqlserver_t *server, int queryidx);
|
||||
void SQL_DeallocResult(queryresult_t *qres);
|
||||
void SQL_ClosePersistantResult(sqlserver_t *server, queryresult_t *qres);
|
||||
void SQL_CloseResult(sqlserver_t *server, queryresult_t *qres);
|
||||
void SQL_CloseAllResults(sqlserver_t *server);
|
||||
char *SQL_ReadField (sqlserver_t *server, queryresult_t *qres, int row, int col, qboolean fields);
|
||||
int SQL_NewServer(char *driver, char **paramstr);
|
||||
int SQL_NewQuery(sqlserver_t *server, int callfunc, int type, int self, float selfid, int other, float otherid, char *str);
|
||||
void SQL_Disconnect(sqlserver_t *server);
|
||||
void SQL_Escape(sqlserver_t *server, char *src, char *dst, int dstlen);
|
||||
char *SQL_Info(sqlserver_t *server);
|
||||
qboolean SQL_Available(void);
|
||||
void SQL_ServerCycle (progfuncs_t *prinst, struct globalvars_s *pr_globals);
|
||||
|
||||
extern cvar_t sql_driver;
|
||||
extern cvar_t sql_host;
|
||||
extern cvar_t sql_username;
|
||||
extern cvar_t sql_password;
|
||||
extern cvar_t sql_defaultdb;
|
||||
|
||||
#define SQLCVAROPTIONS "SQL Defaults"
|
||||
|
||||
#endif
|
|
@ -1,98 +0,0 @@
|
|||
#include "qwsvdef.h"
|
||||
|
||||
#ifdef SQL
|
||||
|
||||
#include "win_mysql.h"
|
||||
|
||||
MYSQLDLL_FUNC1(my_ulonglong, mysql_affected_rows, MYSQL *)
|
||||
MYSQLDLL_FUNC2(my_bool, mysql_autocommit, MYSQL *, my_bool)
|
||||
MYSQLDLL_FUNC4(my_bool, mysql_change_user, MYSQL *, const char *, const char *, const char *)
|
||||
MYSQLDLL_NORETFUNC1(mysql_close, MYSQL *)
|
||||
MYSQLDLL_FUNC1(my_bool, mysql_commit, MYSQL *)
|
||||
MYSQLDLL_NORETFUNC2(mysql_data_seek, MYSQL_RES *, my_ulonglong)
|
||||
MYSQLDLL_FUNC1(int, mysql_dump_debug_info, MYSQL *)
|
||||
MYSQLDLL_FUNC1(unsigned int, mysql_errno, MYSQL *)
|
||||
MYSQLDLL_FUNC1(const char *, mysql_error, MYSQL *)
|
||||
MYSQLDLL_FUNC1(MYSQL_FIELD *, mysql_fetch_field, MYSQL_RES *)
|
||||
MYSQLDLL_FUNC2(MYSQL_FIELD *, mysql_fetch_field_direct, MYSQL_RES *, unsigned int)
|
||||
MYSQLDLL_FUNC1(MYSQL_FIELD *, mysql_fetch_fields, MYSQL_RES *)
|
||||
MYSQLDLL_FUNC1(unsigned long *, mysql_fetch_lengths, MYSQL_RES *)
|
||||
MYSQLDLL_FUNC1(MYSQL_ROW, mysql_fetch_row, MYSQL_RES *)
|
||||
MYSQLDLL_FUNC2(MYSQL_FIELD_OFFSET, mysql_field_seek, MYSQL_RES *, MYSQL_FIELD_OFFSET)
|
||||
MYSQLDLL_FUNC1(unsigned int, mysql_field_count, MYSQL *)
|
||||
MYSQLDLL_FUNC1(MYSQL_FIELD_OFFSET, mysql_field_tell, MYSQL_RES *)
|
||||
MYSQLDLL_NORETFUNC1(mysql_free_result, MYSQL_RES *)
|
||||
MYSQLDLL_FUNC0(const char *, mysql_get_client_info)
|
||||
MYSQLDLL_FUNC0(unsigned long, mysql_get_client_version)
|
||||
MYSQLDLL_FUNC1(const char *, mysql_get_host_info, MYSQL *)
|
||||
MYSQLDLL_FUNC1(unsigned long, mysql_get_server_version, MYSQL *)
|
||||
MYSQLDLL_FUNC1(unsigned int, mysql_get_proto_info, MYSQL *)
|
||||
MYSQLDLL_FUNC1(const char *, mysql_get_server_info, MYSQL *)
|
||||
MYSQLDLL_FUNC1(const char *, mysql_info, MYSQL *)
|
||||
MYSQLDLL_FUNC1(MYSQL *, mysql_init, MYSQL *)
|
||||
MYSQLDLL_FUNC1(my_ulonglong, mysql_insert_id, MYSQL *)
|
||||
MYSQLDLL_FUNC2(int, mysql_kill, MYSQL *, unsigned long)
|
||||
MYSQLDLL_NORETFUNC0(mysql_server_end)
|
||||
MYSQLDLL_FUNC3(int, mysql_server_init, int, char **, char **)
|
||||
MYSQLDLL_FUNC2(MYSQL_RES *, mysql_list_dbs, MYSQL *, const char *)
|
||||
MYSQLDLL_FUNC3(MYSQL_RES *, mysql_list_fields, MYSQL *, const char *, const char *)
|
||||
MYSQLDLL_FUNC1(MYSQL_RES *, mysql_list_processes, MYSQL *)
|
||||
MYSQLDLL_FUNC2(MYSQL_RES *, mysql_list_tables, MYSQL *, const char *)
|
||||
MYSQLDLL_FUNC1(my_bool, mysql_more_results, MYSQL *)
|
||||
MYSQLDLL_FUNC1(int, mysql_next_result, MYSQL *)
|
||||
MYSQLDLL_FUNC1(unsigned int, mysql_num_fields, MYSQL_RES *)
|
||||
MYSQLDLL_FUNC1(my_ulonglong, mysql_num_rows, MYSQL_RES *)
|
||||
MYSQLDLL_FUNC3(int, mysql_options, MYSQL *, enum mysql_option, const char *)
|
||||
MYSQLDLL_FUNC1(int, mysql_ping, MYSQL *)
|
||||
MYSQLDLL_FUNC2(int, mysql_query, MYSQL *, const char *)
|
||||
MYSQLDLL_FUNC8(MYSQL *, mysql_real_connect, MYSQL *, const char *, const char *, const char *, const char *, unsigned int, const char *, unsigned long)
|
||||
MYSQLDLL_FUNC4(unsigned long, mysql_real_escape_string, MYSQL *, char *, const char *, unsigned long)
|
||||
MYSQLDLL_FUNC3(int, mysql_real_query, MYSQL *, const char *, unsigned long)
|
||||
MYSQLDLL_FUNC2(int, mysql_refresh, MYSQL *, unsigned int)
|
||||
// MYSQLDLL_FUNC1(int, mysql_reload, MYSQL *)
|
||||
MYSQLDLL_FUNC1(my_bool, mysql_rollback, MYSQL *)
|
||||
MYSQLDLL_FUNC2(MYSQL_ROW_OFFSET, mysql_row_seek, MYSQL_RES *, MYSQL_ROW_OFFSET)
|
||||
MYSQLDLL_FUNC1(MYSQL_ROW_OFFSET, mysql_row_tell, MYSQL_RES *)
|
||||
MYSQLDLL_FUNC2(int, mysql_select_db, MYSQL *, const char *)
|
||||
MYSQLDLL_FUNC2(int, mysql_set_server_option, MYSQL *, enum enum_mysql_set_option)
|
||||
MYSQLDLL_FUNC1(const char *, mysql_sqlstate, MYSQL *)
|
||||
MYSQLDLL_FUNC2(int, mysql_shutdown, MYSQL *, enum mysql_enum_shutdown_level)
|
||||
MYSQLDLL_FUNC1(const char *, mysql_stat, MYSQL *)
|
||||
MYSQLDLL_FUNC1(MYSQL_RES *, mysql_store_result, MYSQL *)
|
||||
MYSQLDLL_NORETFUNC0(mysql_thread_end)
|
||||
MYSQLDLL_FUNC1(unsigned long, mysql_thread_id, MYSQL *)
|
||||
MYSQLDLL_FUNC0(my_bool, mysql_thread_init)
|
||||
MYSQLDLL_FUNC0(unsigned int, mysql_thread_safe)
|
||||
MYSQLDLL_FUNC1(MYSQL_RES *, mysql_use_result, MYSQL *)
|
||||
MYSQLDLL_FUNC1(unsigned int, mysql_warning_count, MYSQL *)
|
||||
|
||||
/*
|
||||
Not doing this:
|
||||
|
||||
void mysql_set_local_infile_default(MYSQL *mysql)
|
||||
void mysql_set_local_infile_handler(MYSQL *mysql,
|
||||
int (*local_infile_init)(void **, const char *, void *),
|
||||
int (*local_infile_read)(void *, char *, unsigned int),
|
||||
void (*local_infile_end)(void *),
|
||||
int (*local_infile_error)(void *, char*, unsigned int),
|
||||
void *userdata)
|
||||
*/
|
||||
|
||||
int mysql_dll_init()
|
||||
{
|
||||
mysqldll = LoadLibrary("libmysql.dll");
|
||||
|
||||
if (mysqldll == NULL)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mysql_dll_close()
|
||||
{
|
||||
if (mysqldll != NULL)
|
||||
FreeLibrary(mysqldll);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
|
@ -1,130 +0,0 @@
|
|||
#ifndef MYSQLDLL_H
|
||||
#define MYSQLDLL_H
|
||||
|
||||
#include <mysql.h>
|
||||
|
||||
HINSTANCE mysqldll;
|
||||
int mysqldllerror;
|
||||
|
||||
#define MYSQLDLL_NOCONV
|
||||
|
||||
#define MYSQLDLL_LOADFUNC(funcname) \
|
||||
int loaded_##funcname = 0; \
|
||||
int funcload_##funcname() \
|
||||
{ \
|
||||
if (mysqldll) \
|
||||
{ \
|
||||
if (!loaded_##funcname) \
|
||||
{ \
|
||||
cb_##funcname = (DLLFUNC_##funcname)GetProcAddress(mysqldll, #funcname); \
|
||||
loaded_##funcname = 1; \
|
||||
mysqldllerror = GetLastError(); \
|
||||
\
|
||||
} \
|
||||
return (cb_##funcname != NULL); \
|
||||
} \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define MYSQLDLL_FUNC0(returntype, funcname) \
|
||||
typedef returntype (CALLBACK *DLLFUNC_##funcname)(); \
|
||||
DLLFUNC_##funcname cb_##funcname; \
|
||||
MYSQLDLL_LOADFUNC(funcname) \
|
||||
returntype STDCALL funcname() \
|
||||
{ \
|
||||
if (funcload_##funcname()) \
|
||||
return cb_##funcname(); \
|
||||
return (returntype)0; \
|
||||
}
|
||||
|
||||
#define MYSQLDLL_FUNC1(returntype, funcname, paramtype1) \
|
||||
typedef returntype (CALLBACK *DLLFUNC_##funcname)(paramtype1); \
|
||||
DLLFUNC_##funcname cb_##funcname; \
|
||||
MYSQLDLL_LOADFUNC(funcname) \
|
||||
returntype STDCALL funcname(paramtype1 p1) \
|
||||
{ \
|
||||
if (funcload_##funcname()) \
|
||||
return cb_##funcname(p1); \
|
||||
return (returntype)0; \
|
||||
}
|
||||
|
||||
#define MYSQLDLL_FUNC2(returntype, funcname, paramtype1, paramtype2) \
|
||||
typedef returntype (CALLBACK *DLLFUNC_##funcname)(paramtype1, paramtype2); \
|
||||
DLLFUNC_##funcname cb_##funcname; \
|
||||
MYSQLDLL_LOADFUNC(funcname) \
|
||||
returntype STDCALL funcname(paramtype1 p1, paramtype2 p2) \
|
||||
{ \
|
||||
if (funcload_##funcname()) \
|
||||
return cb_##funcname(p1, p2); \
|
||||
return (returntype)0; \
|
||||
}
|
||||
|
||||
#define MYSQLDLL_FUNC3(returntype, funcname, paramtype1, paramtype2, paramtype3) \
|
||||
typedef returntype (CALLBACK *DLLFUNC_##funcname)(paramtype1, paramtype2, paramtype3); \
|
||||
DLLFUNC_##funcname cb_##funcname; \
|
||||
MYSQLDLL_LOADFUNC(funcname) \
|
||||
returntype STDCALL funcname(paramtype1 p1, paramtype2 p2, paramtype3 p3) \
|
||||
{ \
|
||||
if (funcload_##funcname()) \
|
||||
return cb_##funcname(p1, p2, p3); \
|
||||
return (returntype)0; \
|
||||
}
|
||||
|
||||
#define MYSQLDLL_FUNC4(returntype, funcname, paramtype1, paramtype2, paramtype3, paramtype4) \
|
||||
typedef returntype (CALLBACK *DLLFUNC_##funcname)(paramtype1, paramtype2, paramtype3, paramtype4); \
|
||||
DLLFUNC_##funcname cb_##funcname; \
|
||||
MYSQLDLL_LOADFUNC(funcname) \
|
||||
returntype STDCALL funcname(paramtype1 p1, paramtype2 p2, paramtype3 p3, paramtype4 p4) \
|
||||
{ \
|
||||
if (funcload_##funcname()) \
|
||||
return cb_##funcname(p1, p2, p3, p4); \
|
||||
return (returntype)0; \
|
||||
}
|
||||
|
||||
#define MYSQLDLL_FUNC8(returntype, funcname, paramtype1, paramtype2, paramtype3, paramtype4, paramtype5, paramtype6, paramtype7, paramtype8) \
|
||||
typedef returntype (CALLBACK *DLLFUNC_##funcname)(paramtype1, paramtype2, paramtype3, paramtype4, paramtype5, paramtype6, paramtype7, paramtype8); \
|
||||
DLLFUNC_##funcname cb_##funcname; \
|
||||
MYSQLDLL_LOADFUNC(funcname) \
|
||||
returntype STDCALL funcname(paramtype1 p1, paramtype2 p2, paramtype3 p3, paramtype4 p4, paramtype5 p5, paramtype6 p6, paramtype7 p7, paramtype8 p8) \
|
||||
{ \
|
||||
if (funcload_##funcname()) \
|
||||
return cb_##funcname(p1, p2, p3, p4, p5, p6, p7, p8); \
|
||||
return (returntype)0; \
|
||||
}
|
||||
|
||||
#define MYSQLDLL_NORETFUNC0(funcname) \
|
||||
typedef void (CALLBACK *DLLFUNC_##funcname)(); \
|
||||
DLLFUNC_##funcname cb_##funcname; \
|
||||
MYSQLDLL_LOADFUNC(funcname) \
|
||||
void STDCALL funcname() \
|
||||
{ \
|
||||
if (funcload_##funcname()) \
|
||||
cb_##funcname(); \
|
||||
}
|
||||
|
||||
#define MYSQLDLL_NORETFUNC1(funcname, paramtype1) \
|
||||
typedef void (CALLBACK *DLLFUNC_##funcname)(paramtype1); \
|
||||
DLLFUNC_##funcname cb_##funcname; \
|
||||
MYSQLDLL_LOADFUNC(funcname) \
|
||||
void STDCALL funcname(paramtype1 p1) \
|
||||
{ \
|
||||
if (funcload_##funcname()) \
|
||||
cb_##funcname(p1); \
|
||||
}
|
||||
|
||||
#define MYSQLDLL_NORETFUNC2(funcname, paramtype1, paramtype2) \
|
||||
typedef void (CALLBACK *DLLFUNC_##funcname)(paramtype1, paramtype2); \
|
||||
DLLFUNC_##funcname cb_##funcname; \
|
||||
MYSQLDLL_LOADFUNC(funcname) \
|
||||
void STDCALL funcname(paramtype1 p1, paramtype2 p2) \
|
||||
{ \
|
||||
if (funcload_##funcname()) \
|
||||
cb_##funcname(p1, p2); \
|
||||
}
|
||||
|
||||
|
||||
// prototypes
|
||||
int mysql_dll_init();
|
||||
int mysql_dll_close();
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue