From d1c5021c67fc91ea0b686305893cdf186ea27cd6 Mon Sep 17 00:00:00 2001 From: "Marc G. Fournier" Date: Fri, 15 May 1998 20:10:42 +0000 Subject: [PATCH] From: "Aldrin L." Subject: [INTERFACES] mSQL Compatibility Library (fwd) --- contrib/mSQL-interface/README | 85 ++++++++++ contrib/mSQL-interface/mpgsql.c | 275 ++++++++++++++++++++++++++++++++ 2 files changed, 360 insertions(+) create mode 100644 contrib/mSQL-interface/README create mode 100644 contrib/mSQL-interface/mpgsql.c diff --git a/contrib/mSQL-interface/README b/contrib/mSQL-interface/README new file mode 100644 index 0000000000..214d446674 --- /dev/null +++ b/contrib/mSQL-interface/README @@ -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. :] + + + 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. + + + 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 diff --git a/contrib/mSQL-interface/mpgsql.c b/contrib/mSQL-interface/mpgsql.c new file mode 100644 index 0000000000..2f39d7cad9 --- /dev/null +++ b/contrib/mSQL-interface/mpgsql.c @@ -0,0 +1,275 @@ +#include +#include +#include +#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) { +} + -- 2.40.0