]> jfr.im git - irc/quakenet/newserv.git/blobdiff - pqsql/pqsql.c
PQSQL: show the error message on query error.
[irc/quakenet/newserv.git] / pqsql / pqsql.c
index b0bbbb0a64658720d9d0da1e6887fee1273a8940..c0eb002cedbb6ce040cb3acc33af34081559311d 100644 (file)
@@ -9,11 +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 <stdlib.h>
 #include <sys/poll.h>
 #include <stdarg.h>
@@ -47,19 +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;
+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();
@@ -67,6 +73,8 @@ void _init(void) {
 
 void _fini(void) {
   disconnectdb();
+
+  nscheckfreeall(POOL_PQSQL);
 }
 
 PQModuleIdentifier pqgetid(void) {
@@ -96,9 +104,9 @@ void pqfreeid(PQModuleIdentifier identifier) {
       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;
@@ -186,8 +194,8 @@ void dbhandler(int fd, short revents) {
             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:
@@ -210,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);
@@ -226,9 +234,9 @@ void dbhandler(int fd, short revents) {
 /* 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;
@@ -238,14 +246,14 @@ void pqasyncqueryf(int identifier, PQQueryHandler handler, void *tag, int flags,
   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 {
@@ -268,15 +276,16 @@ void pqasyncqueryf(int identifier, PQQueryHandler handler, void *tag, int flags,
   }
 }
 
-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);
 }
 
@@ -304,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) {
@@ -336,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;
   }
 
@@ -384,3 +393,39 @@ char* pqlasterror(PGconn * pgconn) {
   }
   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);
+}