mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-10 22:51:57 +00:00
added persistant queries (UNTESTED), changed sqlopenquery call, added sqlreadfloat, fixed deallocs, self/other is stored on openquery call and is checked against a spawnid on callback call (reset to world when check fails), preliminary add FTE_ENT_UNIQUESPAWNID
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@3006 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
d73b9c0735
commit
9cf2db123c
2 changed files with 354 additions and 189 deletions
|
@ -184,6 +184,7 @@ void ED_Spawned (struct edict_s *ent, int loading)
|
|||
ent->xv->dimension_hit = 255;
|
||||
|
||||
ent->xv->Version = sv.csqcentversion[ent->entnum]+1;
|
||||
ent->xv->uniquespawnid = sv.csqcentversion[ent->entnum];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6362,8 +6363,13 @@ typedef enum
|
|||
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 (struct hack)
|
||||
} queryrequest_t;
|
||||
|
||||
|
@ -6375,7 +6381,7 @@ typedef struct queryresult_s
|
|||
int columns; // fields
|
||||
qboolean eof; // end of query reached
|
||||
MYSQL_RES *result; // result set from mysql
|
||||
char **resultset; // stored result set from partial fetch
|
||||
// char **resultset; // stored result set from partial fetch
|
||||
char error[1]; // error string, "" if none (struct hack)
|
||||
} queryresult_t;
|
||||
|
||||
|
@ -6392,6 +6398,7 @@ typedef struct sqlserver_s
|
|||
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;
|
||||
|
@ -6590,6 +6597,30 @@ int sql_serverworker(void *sref)
|
|||
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 PF_sqlconnect (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
int serverref;
|
||||
|
@ -6683,6 +6714,7 @@ void PF_sqlconnect (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|||
|
||||
sqlservers[serverref] = server;
|
||||
|
||||
server->querynum = 1;
|
||||
server->active = true;
|
||||
server->requestcondv = Sys_CreateConditional();
|
||||
server->resultlock = Sys_CreateMutex();
|
||||
|
@ -6714,221 +6746,346 @@ void PF_sqlconnect (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|||
|
||||
void PF_sqldisconnect (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
int serverref = G_FLOAT(OFS_PARM0);
|
||||
sqlserver_t *server;
|
||||
|
||||
if (!sqlavailable || serverref < 0 || serverref >= sqlservercount || sqlservers[serverref]->active == false)
|
||||
return;
|
||||
|
||||
sqlservers[serverref]->active = false;
|
||||
if (sqlavailable)
|
||||
{
|
||||
server = SQL_GetServer(G_FLOAT(OFS_PARM0), false);
|
||||
if (server)
|
||||
{
|
||||
server->active = false;
|
||||
|
||||
// force the threads to reiterate requests and hopefully terminate
|
||||
Sys_ConditionBroadcast(sqlservers[serverref]->requestcondv);
|
||||
Sys_ConditionBroadcast(server->requestcondv);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PF_sqlopenquery (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
int serverref = G_FLOAT(OFS_PARM0);
|
||||
int callfunc = G_INT(OFS_PARM1);
|
||||
char *querystr = PF_VarString(prinst, 2, pr_globals);
|
||||
int querytype = G_FLOAT(OFS_PARM2);
|
||||
char *querystr = PF_VarString(prinst, 3, pr_globals);
|
||||
int qsize = Q_strlen(querystr);
|
||||
queryrequest_t *qreq = (queryrequest_t *)ZF_Malloc(sizeof(queryrequest_t) + qsize);
|
||||
queryrequest_t *qreq;
|
||||
sqlserver_t *server;
|
||||
int querynum;
|
||||
|
||||
if (!sqlavailable || !qreq || serverref < 0 || serverref >= sqlservercount || sqlservers[serverref]->active == false)
|
||||
if (sqlavailable)
|
||||
{
|
||||
G_FLOAT(OFS_RETURN) = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
server = SQL_GetServer(G_FLOAT(OFS_PARM0), false);
|
||||
if (server)
|
||||
{
|
||||
qreq = (queryrequest_t *)ZF_Malloc(sizeof(queryrequest_t) + qsize);
|
||||
if (qreq)
|
||||
{
|
||||
qreq->persistant = (querytype == 1);
|
||||
qreq->callback = callfunc;
|
||||
querynum = qreq->num = sqlservers[serverref]->querynum;
|
||||
|
||||
// save self and other references
|
||||
if (PROG_TO_EDICT(prinst, pr_global_struct->self)->isfree)
|
||||
qreq->selfent = pr_global_struct->world;
|
||||
else
|
||||
qreq->selfent = pr_global_struct->self;
|
||||
qreq->selfid = PROG_TO_EDICT(prinst, qreq->selfent)->xv->uniquespawnid;
|
||||
if (PROG_TO_EDICT(prinst, pr_global_struct->other)->isfree)
|
||||
qreq->otherent = pr_global_struct->world;
|
||||
else
|
||||
qreq->otherent = pr_global_struct->other;
|
||||
qreq->otherid = PROG_TO_EDICT(prinst, qreq->otherent)->xv->uniquespawnid;
|
||||
|
||||
querynum = qreq->num = server->querynum;
|
||||
// prevent the reference num from getting too big to prevent FP problems
|
||||
if (++sqlservers[serverref]->querynum > 50000)
|
||||
sqlservers[serverref]->querynum -= 100000;
|
||||
if (++server->querynum > 1000000)
|
||||
server->querynum = 1;
|
||||
|
||||
Q_strncpy(qreq->query, querystr, qsize);
|
||||
|
||||
SQL_PushRequest(sqlservers[serverref], qreq);
|
||||
Sys_ConditionSignal(sqlservers[serverref]->requestcondv);
|
||||
SQL_PushRequest(server, qreq);
|
||||
Sys_ConditionSignal(server->requestcondv);
|
||||
|
||||
G_FLOAT(OFS_RETURN) = querynum;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// else we failed so return the error
|
||||
G_FLOAT(OFS_RETURN) = -1;
|
||||
}
|
||||
|
||||
void SQL_CloseCurrentQuery(sqlserver_t *server)
|
||||
void SQL_DeallocResult(queryresult_t *qres)
|
||||
{
|
||||
if (!server->currentresult)
|
||||
return;
|
||||
|
||||
// deallocate current result
|
||||
if (server->currentresult->result)
|
||||
mysql_free_result(server->currentresult->result);
|
||||
if (qres->result)
|
||||
mysql_free_result(qres->result);
|
||||
if (qres->request)
|
||||
Z_Free(qres->request);
|
||||
|
||||
if (server->currentresult->request)
|
||||
Z_Free(server->currentresult->request);
|
||||
Z_Free(server->currentresult);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void PF_sqlclosequery (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
int serverref = G_FLOAT(OFS_PARM0);
|
||||
int queryref = G_FLOAT(OFS_PARM1);
|
||||
sqlserver_t *server;
|
||||
queryresult_t *qres;
|
||||
|
||||
if (!sqlavailable ||
|
||||
serverref < 0 ||
|
||||
serverref >= sqlservercount ||
|
||||
sqlservers[serverref]->active == false ||
|
||||
!sqlservers[serverref]->currentresult ||
|
||||
!sqlservers[serverref]->currentresult->request ||
|
||||
sqlservers[serverref]->currentresult->request->num != queryref)
|
||||
return; // close query isn't for current query
|
||||
|
||||
// TODO: partial resultset logic not implemented yet
|
||||
// TODO: should we allow closing queries out of scope?
|
||||
|
||||
SQL_CloseCurrentQuery(sqlservers[serverref]);
|
||||
}
|
||||
|
||||
void PF_sqlreadfield (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
if (sqlavailable)
|
||||
{
|
||||
int serverref = G_FLOAT(OFS_PARM0);
|
||||
int queryref = G_FLOAT(OFS_PARM1);
|
||||
int row = G_FLOAT(OFS_PARM2);
|
||||
int col = G_FLOAT(OFS_PARM3);
|
||||
|
||||
if (!sqlavailable ||
|
||||
serverref < 0 ||
|
||||
serverref >= sqlservercount ||
|
||||
sqlservers[serverref]->active == false ||
|
||||
!sqlservers[serverref]->currentresult ||
|
||||
!sqlservers[serverref]->currentresult->request ||
|
||||
sqlservers[serverref]->currentresult->request->num != queryref)
|
||||
{ // serverref/queryref validity, also this call must be in the scope of the query callback
|
||||
G_INT(OFS_RETURN) = 0;
|
||||
server = SQL_GetServer(G_FLOAT(OFS_PARM0), false);
|
||||
if (server)
|
||||
{
|
||||
qres = SQL_GetQueryResult(server, G_FLOAT(OFS_PARM1));
|
||||
if (qres)
|
||||
{
|
||||
// TODO: partial resultset logic not implemented yet
|
||||
SQL_CloseResult(server, qres);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sqlservers[serverref]->currentresult->result)
|
||||
{ // TODO: partial resultset logic not implemented yet
|
||||
G_INT(OFS_RETURN) = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// else nothing to close
|
||||
}
|
||||
|
||||
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 (sqlservers[serverref]->currentresult->rows < row ||
|
||||
sqlservers[serverref]->currentresult->columns < col ||
|
||||
col < 0)
|
||||
{ // out of bounds
|
||||
G_INT(OFS_RETURN) = 0;
|
||||
return;
|
||||
}
|
||||
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 = mysql_fetch_field_direct(sqlservers[serverref]->currentresult->result, col);
|
||||
field = mysql_fetch_field_direct(qres->result, col);
|
||||
|
||||
if (!field)
|
||||
{
|
||||
G_INT(OFS_RETURN) = 0;
|
||||
return;
|
||||
return NULL;
|
||||
else
|
||||
return field->name;
|
||||
}
|
||||
else
|
||||
RETURN_TSTRING(field->name);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{ // fetch data
|
||||
MYSQL_ROW sqlrow;
|
||||
|
||||
mysql_data_seek(sqlservers[serverref]->currentresult->result, row);
|
||||
sqlrow = mysql_fetch_row(sqlservers[serverref]->currentresult->result);
|
||||
mysql_data_seek(qres->result, row);
|
||||
sqlrow = mysql_fetch_row(qres->result);
|
||||
if (!sqlrow || !sqlrow[col])
|
||||
return NULL;
|
||||
else
|
||||
return sqlrow[col];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PF_sqlreadfield (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
G_INT(OFS_RETURN) = 0;
|
||||
sqlserver_t *server;
|
||||
queryresult_t *qres;
|
||||
char *data;
|
||||
|
||||
if (sqlavailable)
|
||||
{
|
||||
server = SQL_GetServer(G_FLOAT(OFS_PARM0), false);
|
||||
if (server)
|
||||
{
|
||||
qres = SQL_GetQueryResult(server, G_FLOAT(OFS_PARM1));
|
||||
if (qres)
|
||||
{
|
||||
data = SQL_ReadField(server, qres, G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), true);
|
||||
if (data)
|
||||
{
|
||||
RETURN_TSTRING(data);
|
||||
return;
|
||||
}
|
||||
else
|
||||
RETURN_TSTRING(sqlrow[col]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// else we failed to get anything
|
||||
G_INT(OFS_RETURN) = 0;
|
||||
}
|
||||
|
||||
void PF_sqlreadfloat (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
sqlserver_t *server;
|
||||
queryresult_t *qres;
|
||||
char *data;
|
||||
|
||||
if (sqlavailable)
|
||||
{
|
||||
server = SQL_GetServer(G_FLOAT(OFS_PARM0), false);
|
||||
if (server)
|
||||
{
|
||||
qres = SQL_GetQueryResult(server, G_FLOAT(OFS_PARM1));
|
||||
if (qres)
|
||||
{
|
||||
data = SQL_ReadField(server, qres, G_FLOAT(OFS_PARM2), G_FLOAT(OFS_PARM3), true);
|
||||
if (data)
|
||||
{
|
||||
G_FLOAT(OFS_RETURN) = Q_atof(data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// else we failed to get anything
|
||||
G_FLOAT(OFS_RETURN) = 0;
|
||||
}
|
||||
|
||||
|
||||
void PF_sqlerror (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
sqlserver_t *server;
|
||||
int serverref = G_FLOAT(OFS_PARM0);
|
||||
|
||||
if (!sqlavailable || serverref < 0 || serverref >= sqlservercount)
|
||||
{ // invalid server reference
|
||||
RETURN_TSTRING("");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sqlavailable)
|
||||
{
|
||||
server = SQL_GetServer(G_FLOAT(OFS_PARM0), true);
|
||||
if (server)
|
||||
{
|
||||
if (*svprogfuncs->callargc == 2)
|
||||
{ // query-specific error request
|
||||
int queryref = G_FLOAT(OFS_PARM1);
|
||||
|
||||
if (!sqlservers[serverref]->active ||
|
||||
!sqlservers[serverref]->currentresult ||
|
||||
!sqlservers[serverref]->currentresult->request ||
|
||||
sqlservers[serverref]->currentresult->request->num != queryref)
|
||||
{ // invalid query
|
||||
RETURN_TSTRING("");
|
||||
if (server->active) // didn't check this earlier so check it now
|
||||
{
|
||||
queryresult_t *qres = SQL_GetQueryResult(server, G_FLOAT(OFS_PARM1));
|
||||
if (qres)
|
||||
{
|
||||
RETURN_TSTRING(qres->error);
|
||||
return;
|
||||
}
|
||||
|
||||
RETURN_TSTRING(sqlservers[serverref]->currentresult->error);
|
||||
}
|
||||
else
|
||||
}
|
||||
else if (server->serverresult)
|
||||
{ // server-specific error request
|
||||
if (!sqlservers[serverref]->serverresult)
|
||||
{ // no error result on server, return empty string
|
||||
RETURN_TSTRING("");
|
||||
RETURN_TSTRING(server->serverresult->error);
|
||||
return;
|
||||
}
|
||||
RETURN_TSTRING(sqlservers[serverref]->serverresult->error);
|
||||
}
|
||||
}
|
||||
// else we didn't get a server or query
|
||||
RETURN_TSTRING("");
|
||||
}
|
||||
|
||||
void PF_sqlescape (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
int serverref = G_FLOAT(OFS_PARM0);
|
||||
sqlserver_t *server;
|
||||
char *toescape;
|
||||
char escaped[4096];
|
||||
|
||||
if (sqlavailable)
|
||||
{
|
||||
server = SQL_GetServer(G_FLOAT(OFS_PARM0), false);
|
||||
if (server)
|
||||
{
|
||||
toescape = PR_GetStringOfs(prinst, OFS_PARM1);
|
||||
|
||||
if (!toescape ||
|
||||
!*toescape ||
|
||||
!sqlavailable ||
|
||||
serverref < 0 ||
|
||||
serverref >= sqlservercount ||
|
||||
sqlservers[serverref]->active == false)
|
||||
{ // invalid string or server reference
|
||||
RETURN_TSTRING("");
|
||||
return;
|
||||
}
|
||||
|
||||
mysql_real_escape_string(sqlservers[serverref]->mysql, escaped, toescape, strlen(toescape));
|
||||
if (toescape)
|
||||
{
|
||||
mysql_real_escape_string(server->mysql, escaped, toescape, strlen(toescape));
|
||||
|
||||
RETURN_TSTRING(escaped);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// else invalid string or server reference
|
||||
RETURN_TSTRING("");
|
||||
}
|
||||
|
||||
void PF_sqlversion (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
int serverref = G_FLOAT(OFS_PARM0);
|
||||
sqlserver_t *server;
|
||||
|
||||
if (!sqlavailable ||
|
||||
serverref < 0 ||
|
||||
serverref >= sqlservercount ||
|
||||
sqlservers[serverref]->active == false)
|
||||
{ // invalid string or server reference
|
||||
RETURN_TSTRING("");
|
||||
if (sqlavailable)
|
||||
{
|
||||
server = SQL_GetServer(G_FLOAT(OFS_PARM0), false);
|
||||
if (server)
|
||||
{
|
||||
RETURN_TSTRING(va("mysql: %s", mysql_get_client_info()));
|
||||
return;
|
||||
}
|
||||
|
||||
// no other sql backends yet so just report mysql string for any active
|
||||
RETURN_TSTRING(va("mysql: %s", mysql_get_client_info()));
|
||||
}
|
||||
// else invalid string or server reference
|
||||
RETURN_TSTRING("");
|
||||
}
|
||||
|
||||
// SQL related commands
|
||||
|
@ -6998,7 +7155,7 @@ void SQL_Status_f(void)
|
|||
|
||||
void SQL_Kill_f (void)
|
||||
{
|
||||
int sid;
|
||||
sqlserver_t *server;
|
||||
|
||||
if (Cmd_Argc() < 2)
|
||||
{
|
||||
|
@ -7006,12 +7163,11 @@ void SQL_Kill_f (void)
|
|||
return;
|
||||
}
|
||||
|
||||
sid = atoi(Cmd_Argv(1));
|
||||
|
||||
if (sid >= 0 && sid < sqlservercount)
|
||||
server = SQL_GetServer(atoi(Cmd_Argv(1)), false);
|
||||
if (server)
|
||||
{
|
||||
sqlservers[sid]->active = false;
|
||||
Sys_ConditionBroadcast(sqlservers[sid]->requestcondv);
|
||||
server->active = false;
|
||||
Sys_ConditionBroadcast(server->requestcondv);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -7031,17 +7187,15 @@ void SQL_Cycle (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|||
sqlserver_t *server = sqlservers[i];
|
||||
queryresult_t *qres;
|
||||
|
||||
while (1)
|
||||
while (qres = SQL_PullResult(server))
|
||||
{
|
||||
// get a result off of queue
|
||||
if (!(qres = SQL_PullResult(server)))
|
||||
break;
|
||||
|
||||
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;
|
||||
|
@ -7049,13 +7203,35 @@ void SQL_Cycle (progfuncs_t *prinst, struct globalvars_s *pr_globals)
|
|||
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 && server->currentresult)
|
||||
{ // TODO: is this even worth complaining about?
|
||||
Con_Printf("QC didn't close query %i: %s\n", qres->request->num, qres->request->query);
|
||||
SQL_CloseCurrentQuery(server);
|
||||
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
|
||||
|
@ -7131,7 +7307,6 @@ void SQL_KillServers(void)
|
|||
{
|
||||
sqlserver_t *server = sqlservers[i];
|
||||
queryrequest_t *qreq, *oldqreq;
|
||||
queryresult_t *qres, *oldqres;
|
||||
|
||||
server->active = false; // set thread to kill itself
|
||||
Sys_ConditionBroadcast(server->requestcondv); // force condition check
|
||||
|
@ -7141,34 +7316,16 @@ void SQL_KillServers(void)
|
|||
Sys_DestroyConditional(server->requestcondv);
|
||||
Sys_DestroyMutex(server->resultlock);
|
||||
|
||||
// close orphaned requests
|
||||
qreq = server->requests;
|
||||
while (qreq)
|
||||
{
|
||||
oldqreq = qreq;
|
||||
qreq = qreq->next;
|
||||
Z_Free(qreq);
|
||||
Z_Free(oldqreq);
|
||||
}
|
||||
|
||||
qres = server->results;
|
||||
while (qres)
|
||||
{
|
||||
if (qres->result)
|
||||
mysql_free_result(qres->result);
|
||||
|
||||
if (qres->request)
|
||||
Z_Free(qres->request);
|
||||
|
||||
// TODO: resultset
|
||||
|
||||
oldqres = qres;
|
||||
qres = qres->next;
|
||||
Z_Free(qres);
|
||||
}
|
||||
|
||||
SQL_CloseCurrentQuery(server);
|
||||
|
||||
if (server->serverresult)
|
||||
Z_Free(server->serverresult);
|
||||
SQL_CloseAllResults(server);
|
||||
|
||||
// the alloc'ed connect params should get deallocated by the thread
|
||||
if (server->connectparams)
|
||||
|
@ -7302,6 +7459,7 @@ lh_extension_t QSG_Extensions[] = {
|
|||
{"EXT_DIMENSION_GHOST"},
|
||||
{"FRIK_FILE", 11, NULL, {"stof", "fopen","fclose","fgets","fputs","strlen","strcat","substring","stov","strzone","strunzone"}},
|
||||
{"FTE_CALLTIMEOFDAY", 1, NULL, {"calltimeofday"}},
|
||||
{"FTE_ENT_UNIQUESPAWNID"},
|
||||
{"FTE_EXTENDEDTEXTCODES"},
|
||||
{"FTE_FORCEINFOKEY", 1, NULL, {"forceinfokey"}},
|
||||
{"FTE_GFX_QUAKE3SHADERS"},
|
||||
|
@ -7320,18 +7478,19 @@ lh_extension_t QSG_Extensions[] = {
|
|||
{"FTE_QC_CHECKPVS", 1, NULL, {"checkpvs"}},
|
||||
{"FTE_QC_MATCHCLIENTNAME", 1, NULL, {"matchclientname"}},
|
||||
{"FTE_QC_PAUSED"},
|
||||
{"FTE_QC_SENDPACKET", 1, NULL, {"sendpacket"}},
|
||||
{"FTE_QC_TRACETRIGGER"},
|
||||
{"FTE_SOLID_LADDER"}, //part of a worthy hl implementation. Allows a simple trigger to remove effects of gravity (solid 20)
|
||||
|
||||
#ifdef SQL
|
||||
// serverside SQL functions for managing an SQL database connection
|
||||
{"FTE_SQL", 8, NULL, {"sqlconnect","sqldisconnect","sqlopenquery","sqlclosequery","sqlreadfield","sqlerror","sqlescape","sqlversion"}},
|
||||
{"FTE_SQL", 9, NULL, {"sqlconnect","sqldisconnect","sqlopenquery","sqlclosequery","sqlreadfield","sqlerror","sqlescape","sqlversion",
|
||||
"sqlreadfloat"}},
|
||||
#endif
|
||||
//eperimental advanced strings functions.
|
||||
//reuses the FRIK_FILE builtins (with substring extension)
|
||||
{"FTE_STRINGS", 16, NULL, {"stof", "strlen","strcat","substring","stov","strzone","strunzone",
|
||||
"strstrofs", "str2chr", "chr2str", "strconv", "infoadd", "infoget", "strncmp", "strcasecmp", "strncasecmp"}},
|
||||
{"FTE_QC_SENDPACKET", 1, NULL, {"sendpacket"}},
|
||||
{"FTE_SV_REENTER"},
|
||||
{"FTE_TE_STANDARDEFFECTBUILTINS", 14, NULL, {"te_gunshot", "te_spike", "te_superspike", "te_explosion", "te_tarexplosion", "te_wizspike", "te_knightspike", "te_lavasplash",
|
||||
"te_teleport", "te_lightning1", "te_lightning2", "te_lightning3", "te_lightningblood", "te_bloodqw"}},
|
||||
|
@ -10572,12 +10731,13 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
|
|||
#ifdef SQL
|
||||
{"sqlconnect", PF_sqlconnect, 0, 0, 0, 250}, // #250 float([string host], [string user], [string pass], [string defaultdb], [string driver]) sqlconnect (FTE_SQL)
|
||||
{"sqldisconnect", PF_sqldisconnect, 0, 0, 0, 251}, // #251 void(float serveridx) sqldisconnect (FTE_SQL)
|
||||
{"sqlopenquery", PF_sqlopenquery, 0, 0, 0, 252}, // #252 float(float serveridx, void(float serveridx, float queryidx, float rows, float columns, float eof) callback, string query...) sqlopenquery (FTE_SQL)
|
||||
{"sqlopenquery", PF_sqlopenquery, 0, 0, 0, 252}, // #252 float(float serveridx, void(float serveridx, float queryidx, float rows, float columns, float eof) callback, float querytype, string query) sqlopenquery (FTE_SQL)
|
||||
{"sqlclosequery", PF_sqlclosequery, 0, 0, 0, 253}, // #253 void(float serveridx, float queryidx) sqlclosequery (FTE_SQL)
|
||||
{"sqlreadfield", PF_sqlreadfield, 0, 0, 0, 254}, // #254 string(float serveridx, float queryidx, float row, float column) sqlreadfield (FTE_SQL)
|
||||
{"sqlerror", PF_sqlerror, 0, 0, 0, 255}, // #255 string(float serveridx, [float queryidx]) sqlerror (FTE_SQL)
|
||||
{"sqlescape", PF_sqlescape, 0, 0, 0, 256}, // #256 string(float serveridx, string data) sqlescape (FTE_SQL)
|
||||
{"sqlversion", PF_sqlversion, 0, 0, 0, 257}, // #257 string(float serveridx) sqlversion (FTE_SQL)
|
||||
{"sqlreadfloat", PF_sqlreadfloat, 0, 0, 0, 258}, // #258 float(float serveridx, float queryidx, float row, float column) sqlreadfield (FTE_SQL)
|
||||
#endif
|
||||
|
||||
//EXT_CSQC
|
||||
|
@ -11028,6 +11188,9 @@ void PR_RegisterFields(void) //it's just easier to do it this way.
|
|||
fieldxfloat(Version);
|
||||
fieldxfloat(pvsflags);
|
||||
|
||||
// FTE_ENT_UNIQUESPAWNID
|
||||
fieldxfloat(uniquespawnid);
|
||||
|
||||
//Tell the qc library to split the entity fields each side.
|
||||
//the fields above become < 0, the remaining fields specified by the qc stay where the mod specified, as far as possible (with addons at least).
|
||||
//this means that custom array offsets still work in mods like ktpro.
|
||||
|
|
|
@ -239,6 +239,8 @@ typedef struct extentvars_s
|
|||
float Version;
|
||||
float pvsflags;
|
||||
|
||||
//FTE_ENT_UNIQUESPAWNID
|
||||
float uniquespawnid;
|
||||
#ifdef VM_Q1
|
||||
} extentvars_t;
|
||||
#else
|
||||
|
|
Loading…
Reference in a new issue