log: add \n
[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,
45                                PGresult *ret,
46                                int expected_status,
47                                const char *command,
48                                const char *args,
49                                const char *filename,
50                                int line)
51 {
52   if (ret == NULL)
53   {
54     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
55                      "postgres",
56                      "Postgres failed to allocate result for `%s:%s' at %s:%d\n",
57                      command, args, filename, line);
58     return GNUNET_SYSERR;
59   }
60   if (PQresultStatus (ret) != expected_status)
61   {
62     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
63                      "postgres", _("`%s:%s' failed at %s:%d with error: %s\n"),
64                      command, args, filename, line, PQerrorMessage (dbh));
65     PQclear (ret);
66     return GNUNET_SYSERR;
67   }
68   return GNUNET_OK;
69 }
70
71
72 /**
73  * Run simple SQL statement (without results).
74  *
75  * @param dbh database handle
76  * @param sql statement to run
77  * @param filename filename for error reporting
78  * @param line code line for error reporting
79  * @return #GNUNET_OK on success
80  */
81 int
82 GNUNET_POSTGRES_exec_ (PGconn * dbh,
83                        const char *sql,
84                        const char *filename,
85                        int line)
86 {
87   PGresult *ret;
88
89   ret = PQexec (dbh, sql);
90   if (GNUNET_OK !=
91       GNUNET_POSTGRES_check_result_ (dbh, ret, PGRES_COMMAND_OK, "PQexec", sql,
92                                      filename, line))
93     return GNUNET_SYSERR;
94   PQclear (ret);
95   return GNUNET_OK;
96 }
97
98
99 /**
100  * Prepare SQL statement.
101  *
102  * @param dbh database handle
103  * @param name name for the prepared SQL statement
104  * @param sql SQL code to prepare
105  * @param nparams number of parameters in sql
106  * @param filename filename for error reporting
107  * @param line code line for error reporting
108  * @return #GNUNET_OK on success
109  */
110 int
111 GNUNET_POSTGRES_prepare_ (PGconn *dbh,
112                           const char *name,
113                           const char *sql,
114                           int nparams,
115                           const char *filename,
116                           int line)
117 {
118   PGresult *ret;
119
120   ret = PQprepare (dbh,
121                    name,
122                    sql,
123                    nparams, NULL);
124   if (GNUNET_OK !=
125       GNUNET_POSTGRES_check_result_ (dbh,
126                                      ret,
127                                      PGRES_COMMAND_OK,
128                                      "PQprepare",
129                                      sql,
130                                      filename,
131                                      line))
132     return GNUNET_SYSERR;
133   PQclear (ret);
134   return GNUNET_OK;
135 }
136
137
138 /**
139  * Connect to a postgres database
140  *
141  * @param cfg configuration
142  * @param section configuration section to use to get Postgres configuration options
143  * @return the postgres handle
144  */
145 PGconn *
146 GNUNET_POSTGRES_connect (const struct GNUNET_CONFIGURATION_Handle * cfg,
147                          const char *section)
148 {
149   PGconn *dbh;
150   char *conninfo;
151
152   /* Open database and precompile statements */
153   if (GNUNET_OK !=
154       GNUNET_CONFIGURATION_get_value_string (cfg, section, "CONFIG", &conninfo))
155     conninfo = NULL;
156   dbh = PQconnectdb (conninfo == NULL ? "" : conninfo);
157   GNUNET_free_non_null (conninfo);
158   if (NULL == dbh)
159   {
160     /* FIXME: warn about out-of-memory? */
161     return NULL;
162   }
163   if (PQstatus (dbh) != CONNECTION_OK)
164   {
165     GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, "postgres",
166                      _("Unable to initialize Postgres: %s\n"),
167                      PQerrorMessage (dbh));
168     PQfinish (dbh);
169     return NULL;
170   }
171   return dbh;
172 }
173
174
175 /**
176  * Delete the row identified by the given rowid (qid
177  * in postgres).
178  *
179  * @param dbh database handle
180  * @param stmt name of the prepared statement
181  * @param rowid which row to delete
182  * @return #GNUNET_OK on success
183  */
184 int
185 GNUNET_POSTGRES_delete_by_rowid (PGconn * dbh,
186                                  const char *stmt,
187                                  uint32_t rowid)
188 {
189   uint32_t brow = htonl (rowid);
190   const char *paramValues[] = { (const char *) &brow };
191   int paramLengths[] = { sizeof (brow) };
192   const int paramFormats[] = { 1 };
193   PGresult *ret;
194
195   ret =
196       PQexecPrepared (dbh, stmt, 1,
197                       paramValues,
198                       paramLengths,
199                       paramFormats,
200                       1);
201   if (GNUNET_OK !=
202       GNUNET_POSTGRES_check_result_ (dbh, ret,
203                                      PGRES_COMMAND_OK,
204                                      "PQexecPrepared",
205                                      "delrow",
206                                      __FILE__,
207                                      __LINE__))
208   {
209     return GNUNET_SYSERR;
210   }
211   PQclear (ret);
212   return GNUNET_OK;
213 }
214
215
216 /* end of postgres.c */