/* GNU Mailutils -- a suite of utilities for electronic mail Copyright (C) 2004, 2005, 2007, 2009, 2010 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H # include <config.h> #endif #ifdef HAVE_PGSQL #include <mailutils/mailutils.h> #include <mailutils/sql.h> #include <mailutils/cctype.h> #include <libpq-fe.h> static char * chop (char *str) { int len; for (len = strlen(str); len > 0 && mu_isspace(str[len-1]); len--) ; str[len] = 0; return str; } struct mu_pgsql_data { PGconn *pgconn; PGresult *res; }; static int postgres_init (mu_sql_connection_t conn) { struct mu_pgsql_data *dp = calloc (1, sizeof (*dp)); if (!dp) return ENOMEM; conn->data = dp; return 0; } static int postgres_destroy (mu_sql_connection_t conn) { struct mu_pgsql_data *dp = conn->data; free (dp); conn->data = NULL; return 0; } static int postgres_connect (mu_sql_connection_t conn) { struct mu_pgsql_data *dp = conn->data; char portbuf[16]; char *portstr; if (conn->port == 0) portstr = NULL; else { portstr = portbuf; snprintf (portbuf, sizeof (portbuf), "%d", conn->port); } dp->pgconn = PQsetdbLogin (conn->server, portstr, NULL, NULL, conn->dbname, conn->login, conn->password); if (PQstatus (dp->pgconn) == CONNECTION_BAD) return MU_ERR_SQL; return 0; } static int postgres_disconnect (mu_sql_connection_t conn) { struct mu_pgsql_data *dp = conn->data; PQfinish (dp->pgconn); return 0; } static int postgres_query (mu_sql_connection_t conn, char *query) { struct mu_pgsql_data *dp = conn->data; ExecStatusType stat; dp->res = PQexec (dp->pgconn, query); if (dp->res == NULL) return MU_ERR_SQL; stat = PQresultStatus (dp->res); if (stat != PGRES_COMMAND_OK && stat != PGRES_TUPLES_OK) return MU_ERR_SQL; return 0; } static int postgres_store_result (mu_sql_connection_t conn) { return 0; } static int postgres_release_result (mu_sql_connection_t conn) { struct mu_pgsql_data *dp = conn->data; PQclear (dp->res); dp->res = NULL; return 0; } static int postgres_num_columns (mu_sql_connection_t conn, size_t *np) { struct mu_pgsql_data *dp = conn->data; if (!dp->res) return MU_ERR_NO_RESULT; *np = PQnfields (dp->res); return 0; } static int postgres_num_tuples (mu_sql_connection_t conn, size_t *np) { struct mu_pgsql_data *dp = conn->data; if (!dp->res) return MU_ERR_NO_RESULT; *np = PQntuples (dp->res); return 0; } static int postgres_get_column (mu_sql_connection_t conn, size_t nrow, size_t ncol, char **pdata) { struct mu_pgsql_data *dp = conn->data; if (!dp->res) return MU_ERR_NO_RESULT; *pdata = chop (PQgetvalue (dp->res, nrow, ncol)); return 0; } static int postgres_get_field_number (mu_sql_connection_t conn, const char *fname, size_t *fno) { struct mu_pgsql_data *dp = conn->data; if (!dp->res) return MU_ERR_NO_RESULT; if ((*fno = PQfnumber (dp->res, fname)) == -1) return MU_ERR_NOENT; return 0; } static const char * postgres_errstr (mu_sql_connection_t conn) { struct mu_pgsql_data *dp = conn->data; return PQerrorMessage (dp->pgconn); } MU_DECL_SQL_DISPATCH_T(postgres) = { "postgres", 5432, postgres_init, postgres_destroy, postgres_connect, postgres_disconnect, postgres_query, postgres_store_result, postgres_release_result, postgres_num_tuples, postgres_num_columns, postgres_get_column, postgres_get_field_number, postgres_errstr, }; #endif