2 This file is part of GNUnet
3 Copyright (C) 2014, 2015, 2016, 2017, 2019 GNUnet e.V.
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.
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.
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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @brief helper functions for libpq (PostGres) interactions
23 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
24 * @author Florian Dold
25 * @author Christian Grothoff
31 * Execute a prepared statement.
33 * @param db database handle
34 * @param name name of the prepared statement
35 * @param params parameters to the statement
36 * @return postgres result
39 GNUNET_PQ_exec_prepared (struct GNUNET_PQ_Context *db,
41 const struct GNUNET_PQ_QueryParam *params)
45 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
46 "Running prepared statement `%s' on %p\n",
49 /* count the number of parameters */
51 for (unsigned int i = 0; 0 != params[i].num_params; i++)
52 len += params[i].num_params;
54 /* new scope to allow stack allocation without alloca */
56 /* Scratch buffer for temporary storage */
58 /* Parameter array we are building for the query */
59 void *param_values[len];
60 int param_lengths[len];
61 int param_formats[len];
63 /* How many entries in the scratch buffer are in use? */
67 ConnStatusType status;
71 for (unsigned int i = 0; 0 != params[i].num_params; i++)
73 const struct GNUNET_PQ_QueryParam *x = ¶ms[i];
75 ret = x->conv (x->conv_cls,
86 for (off = 0; off < soff; off++)
87 GNUNET_free (scratch[off]);
93 GNUNET_assert (off == len);
94 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
96 "Executing prepared SQL statement `%s'\n",
98 res = PQexecPrepared (db->conn,
101 (const char **) param_values,
105 if ( (PGRES_COMMAND_OK != PQresultStatus (res)) &&
106 (CONNECTION_OK != (status = PQstatus (db->conn))) )
108 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
110 "Database disconnected on SQL statement `%s' (reconnecting)\n",
112 GNUNET_PQ_reconnect (db);
116 for (off = 0; off < soff; off++)
117 GNUNET_free (scratch[off]);
124 * Free all memory that was allocated in @a rs during
125 * #GNUNET_PQ_extract_result().
127 * @param rs reult specification to clean up
130 GNUNET_PQ_cleanup_result (struct GNUNET_PQ_ResultSpec *rs)
132 for (unsigned int i = 0; NULL != rs[i].conv; i++)
133 if (NULL != rs[i].cleaner)
134 rs[i].cleaner (rs[i].cls,
140 * Extract results from a query result according to the given
143 * @param result result to process
144 * @param[in,out] rs result specification to extract for
145 * @param row row from the result to extract
147 * #GNUNET_YES if all results could be extracted
148 * #GNUNET_SYSERR if a result was invalid (non-existing field)
151 GNUNET_PQ_extract_result (PGresult *result,
152 struct GNUNET_PQ_ResultSpec *rs,
156 return GNUNET_SYSERR;
157 for (unsigned int i = 0; NULL != rs[i].conv; i++)
159 struct GNUNET_PQ_ResultSpec *spec;
163 ret = spec->conv (spec->cls,
169 if (GNUNET_OK != ret)
171 for (unsigned int j = 0; j < i; j++)
172 if (NULL != rs[j].cleaner)
173 rs[j].cleaner (rs[j].cls,
175 return GNUNET_SYSERR;
177 if (NULL != spec->result_size)
178 *spec->result_size = spec->dst_size;