-fix (C) notices
[oweals/gnunet.git] / src / postgres / postgres.c
1 /*
2      This file is part of GNUnet
3      Copyright (C) 2009, 2010, 2012 GNUnet e.V.
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20 /**
21  * @file postgres/postgres.c
22  * @brief library to help with access to a Postgres database
23  * @author Christian Grothoff
24  */
25 #include "platform.h"
26 #include "gnunet_postgres_lib.h"
27
28
29 /**
30  * Check if the result obtained from Postgres has
31  * the desired status code.  If not, log an error, clear the
32  * result and return GNUNET_SYSERR.
33  *
34  * @param dbh database handle
35  * @param ret return value from database operation to check
36  * @param expected_status desired status
37  * @param command description of the command that was run
38  * @param args arguments given to the command
39  * @param filename name of the source file where the command was run
40  * @param line line number in the source file
41  * @return GNUNET_OK if the result is acceptable
42  */
43 int
44 GNUNET_POSTGRES_check_result_ (PGconn * dbh, PGresult * ret,
45                                int expected_status, const char *command,
46                                const char *args, const char *filename, int line)
47 {
48   if (ret == NULL)
49   {
50     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
51                      "postgres",
52                      "Postgres failed to allocate result for `%s:%s' at %s:%d\n",
53                      command, args, filename, line);
54     return GNUNET_SYSERR;
55   }
56   if (PQresultStatus (ret) != expected_status)
57   {
58     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
59                      "postgres", _("`%s:%s' failed at %s:%d with error: %s"),
60                      command, args, filename, line, PQerrorMessage (dbh));
61     PQclear (ret);
62     return GNUNET_SYSERR;
63   }
64   return GNUNET_OK;
65 }
66
67
68 /**
69  * Run simple SQL statement (without results).
70  *
71  * @param dbh database handle
72  * @param sql statement to run
73  * @param filename filename for error reporting
74  * @param line code line for error reporting
75  * @return GNUNET_OK on success
76  */
77 int
78 GNUNET_POSTGRES_exec_ (PGconn * dbh, const char *sql, const char *filename,
79                        int line)
80 {
81   PGresult *ret;
82
83   ret = PQexec (dbh, sql);
84   if (GNUNET_OK !=
85       GNUNET_POSTGRES_check_result_ (dbh, ret, PGRES_COMMAND_OK, "PQexec", sql,
86                                      filename, line))
87     return GNUNET_SYSERR;
88   PQclear (ret);
89   return GNUNET_OK;
90 }
91
92
93 /**
94  * Prepare SQL statement.
95  *
96  * @param dbh database handle
97  * @param name name for the prepared SQL statement
98  * @param sql SQL code to prepare
99  * @param nparams number of parameters in sql
100  * @param filename filename for error reporting
101  * @param line code line for error reporting
102  * @return GNUNET_OK on success
103  */
104 int
105 GNUNET_POSTGRES_prepare_ (PGconn * dbh, const char *name, const char *sql,
106                           int nparams, const char *filename, int line)
107 {
108   PGresult *ret;
109
110   ret = PQprepare (dbh, name, sql, nparams, NULL);
111   if (GNUNET_OK !=
112       GNUNET_POSTGRES_check_result_ (dbh, ret, PGRES_COMMAND_OK, "PQprepare",
113                                      sql, filename, line))
114     return GNUNET_SYSERR;
115   PQclear (ret);
116   return GNUNET_OK;
117 }
118
119
120 /**
121  * Connect to a postgres database
122  *
123  * @param cfg configuration
124  * @param section configuration section to use to get Postgres configuration options
125  * @return the postgres handle
126  */
127 PGconn *
128 GNUNET_POSTGRES_connect (const struct GNUNET_CONFIGURATION_Handle * cfg,
129                          const char *section)
130 {
131   PGconn *dbh;
132   char *conninfo;
133
134   /* Open database and precompile statements */
135   if (GNUNET_OK !=
136       GNUNET_CONFIGURATION_get_value_string (cfg, section, "CONFIG", &conninfo))
137     conninfo = NULL;
138   dbh = PQconnectdb (conninfo == NULL ? "" : conninfo);
139   GNUNET_free_non_null (conninfo);
140   if (NULL == dbh)
141   {
142     /* FIXME: warn about out-of-memory? */
143     return NULL;
144   }
145   if (PQstatus (dbh) != CONNECTION_OK)
146   {
147     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "postgres",
148                      _("Unable to initialize Postgres: %s"),
149                      PQerrorMessage (dbh));
150     PQfinish (dbh);
151     return NULL;
152   }
153   return dbh;
154 }
155
156
157 /**
158  * Delete the row identified by the given rowid (qid
159  * in postgres).
160  *
161  * @param dbh database handle
162  * @param stmt name of the prepared statement
163  * @param rowid which row to delete
164  * @return GNUNET_OK on success
165  */
166 int
167 GNUNET_POSTGRES_delete_by_rowid (PGconn * dbh, const char *stmt, uint32_t rowid)
168 {
169   uint32_t brow = htonl (rowid);
170   const char *paramValues[] = { (const char *) &brow };
171   int paramLengths[] = { sizeof (brow) };
172   const int paramFormats[] = { 1 };
173   PGresult *ret;
174
175   ret =
176       PQexecPrepared (dbh, stmt, 1, paramValues, paramLengths, paramFormats, 1);
177   if (GNUNET_OK !=
178       GNUNET_POSTGRES_check_result_ (dbh, ret, PGRES_COMMAND_OK,
179                                      "PQexecPrepared", "delrow", __FILE__,
180                                      __LINE__))
181   {
182     return GNUNET_SYSERR;
183   }
184   PQclear (ret);
185   return GNUNET_OK;
186 }
187
188
189 /* end of postgres.c */