diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2001-12-06 17:36:21 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2001-12-06 17:36:21 +0000 |
commit | 9339b8ad47f5ae70ac1567a3b87caadd78ed022a (patch) | |
tree | 46ee93b378bebbef132154a237a735cf3eb4f7d8 /src/pgsql.c | |
download | gamma-9339b8ad47f5ae70ac1567a3b87caadd78ed022a.tar.gz gamma-9339b8ad47f5ae70ac1567a3b87caadd78ed022a.tar.bz2 |
Initial revision
Diffstat (limited to 'src/pgsql.c')
-rw-r--r-- | src/pgsql.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/src/pgsql.c b/src/pgsql.c new file mode 100644 index 0000000..956f517 --- /dev/null +++ b/src/pgsql.c @@ -0,0 +1,140 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif +#include <string.h> +#include <guile-sql.h> +#include <libpq-fe.h> + +SCM +s_pgsql_mark(struct sql_connect *conn) +{ + return SCM_BOOL_F; +} + +scm_sizet +s_pgsql_free(struct sql_connect *conn) +{ + PGconn *pgconn = (PGconn*) conn->data; + if (!pgconn) + return 0; + PQfinish(pgconn); + return sizeof(pgconn); +} + +SCM +s_pgsql_connect (char *hostname, int port, + char *dbname, char *user, char *pass, char *why) +{ + PGconn *pgconn; + char buf[24]; + SCM smob; + struct sql_connect *conn; + + snprintf(buf, sizeof buf, "%d", port); + pgconn = PQsetdbLogin(hostname, buf, NULL, NULL, dbname, user, pass); + if (PQstatus(pgconn) == CONNECTION_BAD) + return SCM_BOOL_F; + + smob = sql_connect_create("pgsql"); + conn = (struct sql_connect *)SCM_CDR(smob); + conn->data = pgconn; + return smob; +} + +SCM +result_to_list(PGresult *res) +{ + int i, j; + int ntuples = PQntuples(res); + int nfields = PQnfields(res); + SCM row_head = SCM_EOL, row_tail; + + for (i = 0; i < ntuples; i++) { + SCM new_row; + SCM head = SCM_EOL, tail; + + for (j = 0; j < nfields; j++) { + SCM new_elt; + char *val = PQgetvalue(res, i, j); + SCM_NEWCELL(new_elt); + SCM_SETCAR(new_elt, scm_makfrom0str(val)); + if (head == SCM_EOL) + head = new_elt; + else + SCM_SETCDR(tail, new_elt); + tail = new_elt; + } + + if (head != SCM_EOL) + SCM_SETCDR(tail, SCM_EOL); + + SCM_NEWCELL(new_row); + SCM_SETCAR(new_row, head); + + if (row_head == SCM_EOL) + row_head = new_row; + else + SCM_SETCDR(row_tail, new_row); + row_tail = new_row; + } + if (row_head != SCM_EOL) + SCM_SETCDR(row_tail, SCM_EOL); + return row_head; +} + +SCM +s_pgsql_query(struct sql_connect *conn, char *query) +{ + PGconn *pgconn = (PGconn*) conn->data; + PGresult *res; + SCM cell; + ExecStatusType stat; + + res = PQexec(pgconn, query); + if (!res) + scm_misc_error("s_mgsql_query", + "pgSQL error: ~S", + SCM_LIST1(scm_makfrom0str(PQerrorMessage(pgconn)))); + + stat = PQresultStatus(res); + + switch (stat) { + case PGRES_COMMAND_OK: + /* Successful completion of a command returning no data */ + cell = scm_makenum(strtoul(PQcmdTuples(res), NULL, 0)); + break; + case PGRES_TUPLES_OK: + /* The query successfully executed */ + cell = result_to_list(res); + PQclear(res); + break; + default: + scm_misc_error("s_mgsql_query", + "pgSQL error: ~S", + SCM_LIST1(scm_makfrom0str(PQresStatus(stat)))); + } + + return cell; +} + +void +s_pgsql_close(struct sql_connect *conn) +{ + PGconn *pgconn = (PGconn*) conn->data; + if (!pgconn) + return; + PQfinish(pgconn); + conn->data = NULL; +} + +struct sql_iface pgsql_iface = { + "pgsql", + s_pgsql_mark, + s_pgsql_free, + s_pgsql_connect, + s_pgsql_close, + s_pgsql_query, +}; + + + |