remove 'illegal' (non-reentrant) log logic from signal handler
[oweals/gnunet.git] / src / pq / pq_prepare.c
1 /*
2    This file is part of GNUnet
3    Copyright (C) 2017, 2019 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      SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 /**
21  * @file pq/pq_prepare.c
22  * @brief functions to connect to libpq (PostGres)
23  * @author Christian Grothoff
24  */
25 #include "platform.h"
26 #include "pq.h"
27
28
29 /**
30  * Create a `struct GNUNET_PQ_PreparedStatement`.
31  *
32  * @param name name of the statement
33  * @param sql actual SQL statement
34  * @param num_args number of arguments in the statement
35  * @return initialized struct
36  */
37 struct GNUNET_PQ_PreparedStatement
38 GNUNET_PQ_make_prepare (const char *name,
39                         const char *sql,
40                         unsigned int num_args)
41 {
42   struct GNUNET_PQ_PreparedStatement ps = {
43     .name = name,
44     .sql = sql,
45     .num_arguments = num_args
46   };
47
48   return ps;
49 }
50
51
52 /**
53  * Request creation of prepared statements @a ps from Postgres.
54  *
55  * @param db database to prepare the statements for
56  * @param ps #GNUNET_PQ_PREPARED_STATEMENT_END-terminated array of prepared
57  *            statements.
58  * @return #GNUNET_OK on success,
59  *         #GNUNET_SYSERR on error
60  */
61 int
62 GNUNET_PQ_prepare_statements (struct GNUNET_PQ_Context *db,
63                               const struct GNUNET_PQ_PreparedStatement *ps)
64 {
65   if (db->ps != ps)
66   {
67     /* add 'ps' to list db->ps of prepared statements to run on reconnect! */
68     unsigned int olen = 0; /* length of existing 'db->ps' array */
69     unsigned int nlen = 0; /* length of 'ps' array */
70     struct GNUNET_PQ_PreparedStatement *rps; /* combined array */
71
72     if (NULL != db->ps)
73       while (NULL != db->ps[olen].name)
74         olen++;
75     while (NULL != ps[nlen].name)
76       nlen++;
77     rps = GNUNET_new_array (olen + nlen + 1,
78                             struct GNUNET_PQ_PreparedStatement);
79     if (NULL != db->ps)
80       memcpy (rps,
81               db->ps,
82               olen * sizeof (struct GNUNET_PQ_PreparedStatement));
83     memcpy (&rps[olen],
84             ps,
85             nlen * sizeof (struct GNUNET_PQ_PreparedStatement));
86     GNUNET_free_non_null (db->ps);
87     db->ps = rps;
88   }
89
90   /* actually prepare statements */
91   for (unsigned int i = 0; NULL != ps[i].name; i++)
92   {
93     PGresult *ret;
94
95     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
96                      "pq",
97                      "Preparing SQL statement `%s' as `%s'\n",
98                      ps[i].sql,
99                      ps[i].name);
100     ret = PQprepare (db->conn,
101                      ps[i].name,
102                      ps[i].sql,
103                      ps[i].num_arguments,
104                      NULL);
105     if (PGRES_COMMAND_OK != PQresultStatus (ret))
106     {
107       GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
108                        "pq",
109                        _ ("PQprepare (`%s' as `%s') failed with error: %s\n"),
110                        ps[i].sql,
111                        ps[i].name,
112                        PQerrorMessage (db->conn));
113       PQclear (ret);
114       return GNUNET_SYSERR;
115     }
116     PQclear (ret);
117   }
118   return GNUNET_OK;
119 }
120
121
122 /* end of pq/pq_prepare.c */