X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/47d8702b52d9f0924ef6da861d6991c27172bc1b..8c684fca9c7dbb4a2601628c744be9236ee68641:/pqsql/pqsql.c?ds=sidebyside diff --git a/pqsql/pqsql.c b/pqsql/pqsql.c index afba1e1c..46a547ba 100644 --- a/pqsql/pqsql.c +++ b/pqsql/pqsql.c @@ -9,10 +9,15 @@ #include "../irc/irc_config.h" #include "../core/events.h" #include "../core/hooks.h" +#include "../core/nsmalloc.h" #include "../lib/irc_string.h" #include "../lib/version.h" +#include "../lib/strlfunc.h" #include "pqsql.h" +#define BUILDING_DBAPI +#include "../dbapi/dbapi.h" + #include #include #include @@ -38,6 +43,7 @@ typedef struct pqasyncquery_s { void *tag; PQQueryHandler handler; int flags; + PQModuleIdentifier identifier; struct pqasyncquery_s *next; } pqasyncquery_s; @@ -45,18 +51,21 @@ typedef struct pqtableloaderinfo_s { sstring *tablename; PQQueryHandler init, data, fini; + void *tag; } pqtableloaderinfo_s; pqasyncquery_s *queryhead = NULL, *querytail = NULL; -int dbconnected = 0; -PGconn *dbconn; +static int dbconnected = 0; +static PQModuleIdentifier moduleid = 0; +static PGconn *dbconn; void dbhandler(int fd, short revents); void pqstartloadtable(PGconn *dbconn, void *arg); void dbstatus(int hooknum, void *arg); void disconnectdb(void); void connectdb(void); +char* pqlasterror(PGconn * pgconn); void _init(void) { connectdb(); @@ -64,6 +73,48 @@ void _init(void) { void _fini(void) { disconnectdb(); + + nscheckfreeall(POOL_PQSQL); +} + +PQModuleIdentifier pqgetid(void) { + moduleid++; + if(moduleid < 10) + moduleid = 10; + + return moduleid; +} + +void pqfreeid(PQModuleIdentifier identifier) { + pqasyncquery_s *q, *p; + + if(identifier == 0 || !queryhead) + return; + + if(queryhead->identifier == identifier) { + (queryhead->handler)(NULL, queryhead->tag); + queryhead->identifier = QH_ALREADYFIRED; + } + + for(p=queryhead,q=queryhead->next;q;) { + if(q->identifier == identifier) { + (q->handler)(NULL, q->tag); + p->next = q->next; + + if (q->query_ss) { + freesstring(q->query_ss); + } else { + nsfree(POOL_PQSQL, q->query); + } + nsfree(POOL_PQSQL, q); + q = p->next; + } else { + p = q; + q = q->next; + } + } + + querytail = p; } void connectdb(void) { @@ -74,7 +125,7 @@ void connectdb(void) { return; /* stolen from chanserv as I'm lazy */ - dbhost = getcopyconfigitem("pqsql", "host", "localhost", HOSTLEN); + dbhost = getcopyconfigitem("pqsql", "host", "UNIX", HOSTLEN); dbusername = getcopyconfigitem("pqsql", "username", "newserv", 20); dbpassword = getcopyconfigitem("pqsql", "password", "moo", 20); dbdatabase = getcopyconfigitem("pqsql", "database", "newserv", 20); @@ -89,9 +140,13 @@ void connectdb(void) { freesstring(dbport); return; } - - snprintf(connectstr, sizeof(connectstr), "host=%s port=%s dbname=%s user=%s password=%s", dbhost->content, dbport->content, dbdatabase->content, dbusername->content, dbpassword->content); + if (!strcmp(dbhost->content,"UNIX")) { + snprintf(connectstr, sizeof(connectstr), "dbname=%s user=%s password=%s", dbdatabase->content, dbusername->content, dbpassword->content); + } else { + snprintf(connectstr, sizeof(connectstr), "host=%s port=%s dbname=%s user=%s password=%s", dbhost->content, dbport->content, dbdatabase->content, dbusername->content, dbpassword->content); + } + freesstring(dbhost); freesstring(dbusername); freesstring(dbpassword); @@ -126,24 +181,26 @@ void dbhandler(int fd, short revents) { PQconsumeInput(dbconn); if(!PQisBusy(dbconn)) { /* query is complete */ - if(queryhead->handler) + if(queryhead->handler && queryhead->identifier != QH_ALREADYFIRED) (queryhead->handler)(dbconn, queryhead->tag); while((res = PQgetResult(dbconn))) { - switch(PQresultStatus(res)) { - case PGRES_TUPLES_OK: - Error("pqsql", ERR_WARNING, "Unhandled tuples output (query: %s)", queryhead->query); - break; - - case PGRES_NONFATAL_ERROR: - case PGRES_FATAL_ERROR: - /* if a create query returns an error assume it went ok, paul will winge about this */ - if(!(queryhead->flags & QH_CREATE)) - Error("pqsql", ERR_WARNING, "Unhandled error response (query: %s)", queryhead->query); - break; + if(queryhead->identifier != QH_ALREADYFIRED) { + switch(PQresultStatus(res)) { + case PGRES_TUPLES_OK: + Error("pqsql", ERR_WARNING, "Unhandled tuples output (query: %s)", queryhead->query); + break; + + case PGRES_NONFATAL_ERROR: + case PGRES_FATAL_ERROR: + /* if a create query returns an error assume it went ok, paul will winge about this */ + if(!(queryhead->flags & DB_CREATE)) + Error("pqsql", ERR_WARNING, "Unhandled error response (query: %s)", queryhead->query); + break; - default: - break; + default: + break; + } } PQclear(res); @@ -161,10 +218,10 @@ void dbhandler(int fd, short revents) { qqp->query_ss=NULL; qqp->query=NULL; } else if (qqp->query) { - free(qqp->query); + nsfree(POOL_PQSQL, qqp->query); qqp->query=NULL; } - free(qqp); + nsfree(POOL_PQSQL, qqp); if(queryhead) { /* Submit the next query */ PQsendQuery(dbconn, queryhead->query); @@ -175,11 +232,11 @@ void dbhandler(int fd, short revents) { } /* sorry Q9 */ -void pqasyncqueryf(PQQueryHandler handler, void *tag, int flags, char *format, ...) { +void pqasyncqueryf(int identifier, PQQueryHandler handler, void *tag, int flags, char *format, ...) { char querybuf[8192]; - va_list va; int len; pqasyncquery_s *qp; + va_list va; if(!pqconnected()) return; @@ -189,14 +246,14 @@ void pqasyncqueryf(PQQueryHandler handler, void *tag, int flags, char *format, . va_end(va); /* PPA: no check here... */ - qp = (pqasyncquery_s *)malloc(sizeof(pqasyncquery_s)); + qp = (pqasyncquery_s *)nsmalloc(POOL_PQSQL, sizeof(pqasyncquery_s)); if(!qp) Error("pqsql",ERR_STOP,"malloc() failed in pqsql.c"); /* Use sstring or allocate (see above rant) */ if (len > SSTRING_MAX) { - qp->query = (char *)malloc(len+1); + qp->query = (char *)nsmalloc(POOL_PQSQL, len+1); strcpy(qp->query,querybuf); qp->query_ss=NULL; } else { @@ -207,6 +264,7 @@ void pqasyncqueryf(PQQueryHandler handler, void *tag, int flags, char *format, . qp->handler = handler; qp->next = NULL; /* shove them at the end */ qp->flags = flags; + qp->identifier = identifier; if(querytail) { querytail->next = qp; @@ -218,15 +276,16 @@ void pqasyncqueryf(PQQueryHandler handler, void *tag, int flags, char *format, . } } -void pqloadtable(char *tablename, PQQueryHandler init, PQQueryHandler data, PQQueryHandler fini) +void pqloadtable(char *tablename, PQQueryHandler init, PQQueryHandler data, PQQueryHandler fini, void *tag) { pqtableloaderinfo_s *tli; - tli=(pqtableloaderinfo_s *)malloc(sizeof(pqtableloaderinfo_s)); + tli=(pqtableloaderinfo_s *)nsmalloc(POOL_PQSQL, sizeof(pqtableloaderinfo_s)); tli->tablename=getsstring(tablename, 100); tli->init=init; tli->data=data; tli->fini=fini; + tli->tag=tag; pqasyncquery(pqstartloadtable, tli, "SELECT COUNT(*) FROM %s", tli->tablename->content); } @@ -254,19 +313,19 @@ void pqstartloadtable(PGconn *dbconn, void *arg) Error("pqsql", ERR_INFO, "Found %lu entries in table %s, scheduling load.", count, tli->tablename->content); - pqasyncquery(tli->init, NULL, "BEGIN"); + pqasyncquery(tli->init, tli->tag, "BEGIN"); pqasyncquery(NULL, NULL, "DECLARE table%lx%lx CURSOR FOR SELECT * FROM %s", tablecrc, count, tli->tablename->content); for (i=0;(count - i) > 1000; i+=1000) - pqasyncquery(tli->data, NULL, "FETCH 1000 FROM table%lx%lx", tablecrc, count); + pqasyncquery(tli->data, tli->tag, "FETCH 1000 FROM table%lx%lx", tablecrc, count); - pqasyncquery(tli->data, NULL, "FETCH ALL FROM table%lx%lx", tablecrc, count); + pqasyncquery(tli->data, tli->tag, "FETCH ALL FROM table%lx%lx", tablecrc, count); pqasyncquery(NULL, NULL, "CLOSE table%lx%lx", tablecrc, count); - pqasyncquery(tli->fini, NULL, "COMMIT"); + pqasyncquery(tli->fini, tli->tag, "COMMIT"); freesstring(tli->tablename); - free(tli); + nsfree(POOL_PQSQL, tli); } void disconnectdb(void) { @@ -286,10 +345,10 @@ void disconnectdb(void) { qqp->query_ss=NULL; qqp->query=NULL; } else if (qqp->query) { - free(qqp->query); + nsfree(POOL_PQSQL, qqp->query); qqp->query=NULL; } - free(qqp); + nsfree(POOL_PQSQL, qqp); qqp = nqqp; } @@ -321,18 +380,52 @@ int pqconnected(void) { return dbconnected; } -char* pqlasterror(PGconn * pgconn) -{ - static char errormsg[PQ_ERRORMSG_LENGTH]; +char* pqlasterror(PGconn * pgconn) { + static char errormsg[PQ_ERRORMSG_LENGTH + 1]; int i; - char *error = PQerrorMessage(pgconn); - int len = min(sizeof(errormsg),strlen(error)); - strncpy(errormsg, error, len - 1); - errormsg[len - 1] = '\0'; - for(i=0;irow = -1; + r->result = PQgetResult(c); + r->rows = PQntuples(r->result); + + return r; +} + +int pqfetchrow(PQResult *res) { + if(res->row + 1 == res->rows) + return 0; + + res->row++; + + return 1; +} + +char *pqgetvalue(PQResult *res, int column) { + return PQgetvalue(res->result, res->row, column); +} + +void pqclear(PQResult *res) { + if(!res) + return; + + if(res->result) + PQclear(res->result); + + nsfree(POOL_PQSQL, res); +}