]> granicus.if.org Git - postgresql/commitdiff
From: "Aldrin L." <aldrin@americasnet.com>
authorMarc G. Fournier <scrappy@hub.org>
Fri, 15 May 1998 20:10:42 +0000 (20:10 +0000)
committerMarc G. Fournier <scrappy@hub.org>
Fri, 15 May 1998 20:10:42 +0000 (20:10 +0000)
Subject: [INTERFACES] mSQL Compatibility Library (fwd)

contrib/mSQL-interface/README [new file with mode: 0644]
contrib/mSQL-interface/mpgsql.c [new file with mode: 0644]

diff --git a/contrib/mSQL-interface/README b/contrib/mSQL-interface/README
new file mode 100644 (file)
index 0000000..214d446
--- /dev/null
@@ -0,0 +1,85 @@
+Hello! :)
+
+(Sorry for my english. But if i wrote in portuguese, you wouldn't
+ understand nothing. :])
+
+       I found it's the right place to post this. I'm a newcomer in these
+lists. I hope i did it right. :]
+
+<BOREDOM>
+       When i started using SQL, i started with mSQL. I developed a lot
+of useful apps for me and my job with C, mainly because i loved it's
+elegant, simple api. But for a large project i'm doing in these days, i
+thought is was not enough, because it felt a lot of features i started to
+need, like security and subselects. (and it's not free :))
+       So after looking at the options, choose to start again with
+postgres. It offered everything that i needed, and the documentation is
+really good (remember me to thank the one who wrote'em).
+       But for my little apps, i needed to start porting them to libpq.
+After looking at pq's syntax, i found it was better to write a bridge
+between the mSQL api and libpq. I found that rewriting the libmsql.a
+routines that calls libpq would made things much easier. I guess the
+results are quite good right now.
+</BOREDOM>
+
+       Ok. Lets' summarize it:
+
+       mpgsql.c is the bridge. Acting as a wrapper, it's really good,
+since i could run mSQL. But it's not accurate. Some highlights:
+
+       CONS:
+       * It's not well documented 
+               (this post is it's first documentation attempt, in fact);
+       * It doesn't handle field types correctly. I plan to fix it,
+         if people start doing feedbacks;
+       * It's limited to 10 simultaneous connections. I plan to enhance
+         this, i'm just figuring out;
+       * I'd like to make it reentrant/thread safe, although i don't
+         think this could be done without changing the API structure;
+       * Error Management should be better. This is my first priority
+          now;
+       * Some calls are just empty implementations.
+
+       PROS:
+       * the mSQL Monitor runs Okay. :]
+       * It's really cool. :)
+       * Make mSQL-made applications compatible with postgresql just by
+         changing link options.
+       * Uses postgreSQL. :]
+       * the mSQL API it's far easier to use and understand than libpq.
+          Consider this example:
+
+#include "msql.h"
+
+void main(int argc, char **argv, char **envp) {
+   int sid;
+       
+   sid = msqlConnect(NULL); /* Connects via unix socket */
+
+   if (sid >= 0) {
+      m_result *rlt;
+      m_row *row;
+      msqlSelectDB(sid, "hosts");
+      if (msqlQuery(sid, "select host_id from hosts")) {
+        rlt = msqlStoreResult();
+         while (row = (m_row*)msqlFetchRow(rlt)) 
+            printf("hostid: %s\n", row[0]);
+         msqlFreeResult(rlt);
+      }
+      msqlClose(sid);
+   }
+}
+
+       I enclose mpgsql.c inside. I'd like to maintain it, and (maybe, am
+i dreaming) make it as part of the pgsql distribution. I guess it doesn't
+depends on me, but mainly on it's acceptance by its users.
+
+       Hm... i forgot: you'll need a msql.h copy, since it's copyrighted
+by Hughes Technologies Pty Ltd. If you haven't it yes, fetch one
+from www.hughes.com.au.
+
+       I would like to catch users ideas. My next goal is to add better
+error handling, and to make it better documented, and try to let relshow
+run through it. :)
+
+       done. Aldrin Leal <aldrin@americasnet.com>
diff --git a/contrib/mSQL-interface/mpgsql.c b/contrib/mSQL-interface/mpgsql.c
new file mode 100644 (file)
index 0000000..2f39d7c
--- /dev/null
@@ -0,0 +1,275 @@
+#include <time.h>
+#include <string.h>
+#include <stdlib.h>
+#include "msql.h"
+#include "libpq-fe.h"
+
+#define HNDMAX 10
+
+PGconn *PGh[HNDMAX] = {
+   NULL, NULL, NULL, NULL, NULL,
+   NULL, NULL, NULL, NULL, NULL
+};
+
+#define E_NOHANDLERS 0
+
+char *msqlErrors[] = {
+   "Out of database handlers."
+};
+
+char msqlErrMsg[BUFSIZ], *tfrom = "dunno";
+PGresult *queryres = NULL;
+
+int msqlConnect (char *host) {
+   int count;
+   
+   for (count = 0; count < HNDMAX; count++) 
+      if (PGh[count] == NULL) break;
+      
+   if (count == HNDMAX) {
+      strncpy(msqlErrMsg, msqlErrors[E_NOHANDLERS], BUFSIZ);
+      return -1;
+   }
+
+   PGh[count] = malloc(sizeof (PGconn));
+   PGh[count]->pghost = host ? strdup(host) : NULL;
+   return count;
+}
+
+int msqlSelectDB(int handle, char *dbname) {
+   char *options = calloc(1, BUFSIZ);
+   char *e = getenv("PG_OPTIONS");
+   
+   if (e == NULL) 
+      e = "";
+   
+   if (PGh[handle]->pghost) {
+      strcat(options, "host=");
+      strncat(options, PGh[handle]->pghost, BUFSIZ);
+      strncat(options, " ", BUFSIZ);
+      free(PGh[handle]->pghost);
+      PGh[handle]->pghost = NULL;
+   }
+   strncat(options, "dbname=", BUFSIZ);
+   strncat(options, dbname, BUFSIZ);
+   strncat(options, " ", BUFSIZ);
+   strncat(options, e, BUFSIZ);
+   free(PGh[handle]);
+   PGh[handle] = PQconnectdb(options);
+   free(options);
+   strncpy(msqlErrMsg, PQerrorMessage(PGh[handle]), BUFSIZ);
+   return (PQstatus(PGh[handle]) == CONNECTION_BAD ? -1 : 0);
+}
+
+int msqlQuery(int handle, char *query) {
+   char *tq = strdup(query);
+   char *p = tq;
+   PGresult *res;
+   PGconn *conn = PGh[handle];
+   ExecStatusType rcode;
+   
+   res = PQexec(conn, p);
+
+   rcode = PQresultStatus(res);
+    
+   if (rcode == PGRES_TUPLES_OK) {
+      queryres = res;
+      return PQntuples(res);
+   } else if (rcode == PGRES_FATAL_ERROR || rcode == PGRES_NONFATAL_ERROR) {
+      PQclear(res);
+      queryres = NULL;
+      return -1;
+   } else {
+      PQclear(res);
+      queryres = NULL;
+      return 0;
+   }
+}
+
+int msqlCreateDB (int a, char*b) {
+   char tbuf[BUFSIZ];
+   sprintf(tbuf, "create database %s", b);
+   return msqlQuery(a, tbuf) >= 0 ? 0 : -1;
+}
+
+int msqlDropDB (int a, char* b) {
+   char tbuf[BUFSIZ];
+   sprintf(tbuf, "drop database %s", b);
+   return msqlQuery(a, tbuf) >= 0 ? 0 : -1;
+}
+
+int msqlShutdown(int a) {
+}
+
+int msqlGetProtoInfo(void) {
+}
+
+int msqlReloadAcls(int a) {
+}
+
+char *msqlGetServerInfo(void) {
+}
+
+char *msqlGetHostInfo(void) {
+}
+
+char *msqlUnixTimeToDate(time_t date) {
+}
+
+char *msqlUnixTimeToTime(time_t time) {
+}
+
+void msqlClose(int a) {
+    PQfinish(PGh[a]);
+    PGh[a] = NULL;
+    if (queryres) {
+       free(queryres);
+       queryres = NULL;
+    }
+}
+
+void msqlDataSeek(m_result *result, int count) {
+   int c;
+   result->cursor = result->queryData;
+   for (c = 1; c < count; c++)
+      if (result->cursor->next)
+         result->cursor = result->cursor->next;
+}
+
+void msqlFieldSeek(m_result *result, int count) {
+   int c;
+   result->fieldCursor = result->fieldData;
+   for (c = 1; c < count; c++)
+      if (result->fieldCursor->next)
+         result->fieldCursor = result->fieldCursor->next;
+}
+
+void msqlFreeResult(m_result *result) {
+   if (result) {
+      /* Clears fields */
+      free(result->fieldData);
+      result->cursor = result->queryData;
+      while (result->cursor) {
+         int c;
+         m_row m = result->cursor->data;
+         
+         for (c = 0; m[c]; c++)
+            free(m[c]);
+
+         result->cursor = result->cursor->next;
+      } 
+      free(result->queryData);
+      free(result);
+   }  
+}
+
+m_row msqlFetchRow(m_result *row) {
+   m_data *r = row->cursor;
+   if (r) {
+      row->cursor = row->cursor->next;
+      return (m_row)r->data;
+   }
+   return (m_row)NULL;
+}
+
+m_seq *msqlGetSequenceInfo(int a, char *b) {
+}
+
+m_field *msqlFetchField (m_result *mr) {
+   m_field *m = (m_field*)mr->fieldCursor;
+   if (m) {
+      mr->fieldCursor = mr->fieldCursor->next;
+      return m;
+   }
+   return NULL;
+}
+
+m_result *msqlListDBs(int a) {
+   m_result *m;
+   if (msqlQuery(a, "select datname from pg_database") > 0) {
+      m = msqlStoreResult();
+      return m;
+   } else return NULL;
+}
+
+m_result *msqlListTables(int a) {
+   m_result *m;
+   char tbuf[BUFSIZ];
+   
+   sprintf(tbuf, "select relname from pg_class where relkind='r' and relowner=%d", getuid());
+   if (msqlQuery(a, tbuf) > 0) {
+      m = msqlStoreResult();
+      return m;
+   } else return NULL;
+}
+
+m_result *msqlListFields(int a, char *b) {
+   
+}
+
+m_result *msqlListIndex(int a, char *b, char *c) {
+   m_result *m;
+   char tbuf[BUFSIZ];
+   
+   sprintf(tbuf, "select relname from pg_class where relkind='i' and relowner=%d", getuid());
+   if (msqlQuery(a, tbuf) > 0) {
+      m = msqlStoreResult();
+      return m;
+   } else return NULL;
+}
+
+m_result *msqlStoreResult(void) {
+   if (queryres) {
+      m_result *mr = malloc(sizeof(m_result));
+      m_fdata *mf;
+      m_data *md;
+      int count;
+      mr->queryData = mr->cursor = NULL;
+      mr->numRows = PQntuples(queryres);  
+      mr->numFields = PQnfields(queryres);
+      
+      mf = calloc(PQnfields(queryres), sizeof(m_fdata));      
+      for (count = 0; count < PQnfields(queryres); count++) {
+         (m_fdata*)(mf+count)->field.name = strdup(PQfname(queryres, count)); 
+         (m_fdata*)(mf+count)->field.table = tfrom; 
+         (m_fdata*)(mf+count)->field.type = CHAR_TYPE;
+         (m_fdata*)(mf+count)->field.length = PQfsize(queryres, count);
+         (m_fdata*)(mf+count)->next = (m_fdata*)(mf+count+1);
+      }
+      (m_fdata*)(mf+count-1)->next = NULL;
+      
+      md = calloc(PQntuples(queryres), sizeof(m_data));
+      for (count = 0; count < PQntuples(queryres); count++) {
+         m_row rows = calloc(PQnfields(queryres)*sizeof(m_row)+1, 1);
+         int c;
+         
+         for (c = 0; c < PQnfields(queryres); c++) {
+            rows[c] = strdup(PQgetvalue(queryres, count, c));
+         }
+         (m_data*)(md+count)->data = rows;
+         
+         (m_data*)(md+count)->width = PQnfields(queryres);
+         (m_data*)(md+count)->next = (m_data*)(md+count+1);
+      }
+      (m_data*)(md+count-1)->next = NULL;
+      
+      mr->queryData = mr->cursor = md;
+      mr->fieldCursor = mr->fieldData = mf;
+
+      return mr;
+   } else return NULL;
+}
+
+time_t msqlDateToUnixTime(char *a) {
+}
+
+time_t msqlTimeToUnixTime(char *b) {
+}
+
+char *msql_tmpnam(void) {
+   return tmpnam("/tmp/msql.XXXXXX");
+}
+
+int msqlLoadConfigFile(char *a) {
+}
+