/* This file is part of guile-sql. Copyright (C) 2002 Sergey Poznyakoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include 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, };