f089d7c0ac542e02427988456c4e041937379db4
[oweals/gnunet.git] / src / pq / pq_exec.c
1 /*
2   This file is part of GNUnet
3   Copyright (C) 2017 GNUnet e.V.
4
5   GNUnet is free software: you can redistribute it and/or modify it
6   under the terms of the GNU Affero General Public License as published
7   by the Free Software Foundation, either version 3 of the License,
8   or (at your 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   Affero General Public License for more details.
14
15   You should have received a copy of the GNU Affero General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 /**
19  * @file pq/pq_exec.c
20  * @brief functions to execute plain SQL statements (PostGres)
21  * @author Christian Grothoff
22  */
23 #include "platform.h"
24 #include "gnunet_util_lib.h"
25 #include "gnunet_pq_lib.h"
26
27
28 /**
29  * Create a `struct GNUNET_PQ_ExecuteStatement` where errors are fatal.
30  *
31  * @param sql actual SQL statement
32  * @return initialized struct
33  */
34 struct GNUNET_PQ_ExecuteStatement
35 GNUNET_PQ_make_execute (const char *sql)
36 {
37   struct GNUNET_PQ_ExecuteStatement es = {
38     .sql = sql,
39     .ignore_errors = GNUNET_NO
40   };
41
42   return es;
43 }
44
45
46 /**
47  * Create a `struct GNUNET_PQ_ExecuteStatement` where errors should
48  * be tolerated.
49  *
50  * @param sql actual SQL statement
51  * @return initialized struct
52  */
53 struct GNUNET_PQ_ExecuteStatement
54 GNUNET_PQ_make_try_execute (const char *sql)
55 {
56   struct GNUNET_PQ_ExecuteStatement es = {
57     .sql = sql,
58     .ignore_errors = GNUNET_YES
59   };
60
61   return es;
62 }
63
64
65 /**
66  * Request execution of an array of statements @a es from Postgres.
67  *
68  * @param connection connection to execute the statements over
69  * @param es #GNUNET_PQ_PREPARED_STATEMENT_END-terminated array of prepared
70  *            statements.
71  * @return #GNUNET_OK on success (modulo statements where errors can be ignored)
72  *         #GNUNET_SYSERR on error
73  */
74 int
75 GNUNET_PQ_exec_statements (PGconn *connection,
76                            const struct GNUNET_PQ_ExecuteStatement *es)
77 {
78   for (unsigned int i=0; NULL != es[i].sql; i++)
79   {
80     PGresult *result;
81
82     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
83                 "Running statement `%s' on %p\n",
84                 es[i].sql,
85                 connection);
86     result = PQexec (connection,
87                      es[i].sql);
88     if ( (GNUNET_NO == es[i].ignore_errors) &&
89          (PGRES_COMMAND_OK != PQresultStatus (result)) )
90     {
91       GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
92                        "pq",
93                        "Failed to execute `%s': %s/%s/%s/%s/%s",
94                        es[i].sql,
95                        PQresultErrorField (result,
96                                            PG_DIAG_MESSAGE_PRIMARY),
97                        PQresultErrorField (result,
98                                            PG_DIAG_MESSAGE_DETAIL),
99                        PQresultErrorMessage (result),
100                        PQresStatus (PQresultStatus (result)),
101                        PQerrorMessage (connection));
102       PQclear (result);
103       return GNUNET_SYSERR;
104     }
105     PQclear (result);
106   }
107   return GNUNET_OK;
108 }
109
110
111 /* end of pq/pq_exec.c */