#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 <stdlib.h>
#include <sys/poll.h>
#include <stdarg.h>
{
sstring *tablename;
PQQueryHandler init, data, fini;
+ void *tag;
} pqtableloaderinfo_s;
pqasyncquery_s *queryhead = NULL, *querytail = NULL;
-int dbconnected = 0;
+static int dbconnected = 0;
static PQModuleIdentifier moduleid = 0;
-PGconn *dbconn;
+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();
void _fini(void) {
disconnectdb();
+
+ nscheckfreeall(POOL_PQSQL);
}
PQModuleIdentifier pqgetid(void) {
if (q->query_ss) {
freesstring(q->query_ss);
} else {
- free(q->query);
+ nsfree(POOL_PQSQL, q->query);
}
- free(q);
+ nsfree(POOL_PQSQL, q);
q = p->next;
} else {
p = q;
if(queryhead->identifier != QH_ALREADYFIRED) {
switch(PQresultStatus(res)) {
case PGRES_TUPLES_OK:
- Error("pqsql", ERR_WARNING, "Unhandled tuples output (query: %s)", queryhead->query);
+ if(!(queryhead->flags & DB_CALL))
+ 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);
+ if(!(queryhead->flags & DB_CREATE))
+ Error("pqsql", ERR_WARNING, "Unhandled error response (query: %s): %s", queryhead->query, PQresultErrorMessage(res));
break;
default:
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);
/* sorry Q9 */
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;
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 {
}
}
-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);
}
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) {
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;
}
}
return errormsg;
}
+
+PQResult *pqgetresult(PGconn *c) {
+ PQResult *r;
+ if(!c)
+ return NULL;
+
+ r = (PQResult *)nsmalloc(POOL_PQSQL, sizeof(PQResult));
+ r->row = -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);
+}