2 This file is part of GNUnet
3 Copyright (C) 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
21 * @file pq/pq_connect.c
22 * @brief functions to connect to libpq (PostGres)
23 * @author Christian Grothoff
30 * Function called by libpq whenever it wants to log something.
31 * We already log whenever we care, so this function does nothing
32 * and merely exists to silence the libpq logging.
34 * @param arg the SQL connection that was used
35 * @param res information about some libpq event
38 pq_notice_receiver_cb (void *arg,
41 /* do nothing, intentionally */
48 * Function called by libpq whenever it wants to log something.
49 * We log those using the GNUnet logger.
51 * @param arg the SQL connection that was used
52 * @param message information about some libpq event
55 pq_notice_processor_cb (void *arg,
59 GNUNET_log_from (GNUNET_ERROR_TYPE_INFO,
67 * Create a connection to the Postgres database using @a config_str
68 * for the configuration. Initialize logging via GNUnet's log
69 * routines and disable Postgres's logger. Also ensures that the
70 * statements in @a es are executed whenever we (re)connect to the
71 * database, and that the prepared statements in @a ps are "ready".
72 * If statements in @es fail that were created with
73 * #GNUNET_PQ_make_execute(), then the entire operation fails.
75 * The caller MUST ensure that @a es and @a ps remain allocated and
76 * initialized in memory until #GNUNET_PQ_disconnect() is called,
77 * as they may be needed repeatedly and no copy will be made.
79 * @param config_str configuration to use
80 * @param es #GNUNET_PQ_PREPARED_STATEMENT_END-terminated
81 * array of statements to execute upon EACH connection, can be NULL
82 * @param ps array of prepared statements to prepare, can be NULL
83 * @return NULL on error
85 struct GNUNET_PQ_Context *
86 GNUNET_PQ_connect (const char *config_str,
87 const struct GNUNET_PQ_ExecuteStatement *es,
88 const struct GNUNET_PQ_PreparedStatement *ps)
90 struct GNUNET_PQ_Context *db;
91 unsigned int elen = 0;
92 unsigned int plen = 0;
95 while (NULL != es[elen].sql)
98 while (NULL != ps[plen].name)
101 db = GNUNET_new (struct GNUNET_PQ_Context);
102 db->config_str = GNUNET_strdup (config_str);
105 db->es = GNUNET_new_array (elen + 1,
106 struct GNUNET_PQ_ExecuteStatement);
109 elen * sizeof (struct GNUNET_PQ_ExecuteStatement));
113 db->ps = GNUNET_new_array (plen + 1,
114 struct GNUNET_PQ_PreparedStatement);
117 plen * sizeof (struct GNUNET_PQ_PreparedStatement));
119 GNUNET_PQ_reconnect (db);
120 if (NULL == db->conn)
122 GNUNET_free (db->config_str);
131 * Reinitialize the database @a db if the connection is down.
133 * @param db database connection to reinitialize
136 GNUNET_PQ_reconnect_if_down (struct GNUNET_PQ_Context *db)
138 if (CONNECTION_BAD != PQstatus (db->conn))
140 GNUNET_PQ_reconnect (db);
145 * Reinitialize the database @a db.
147 * @param db database connection to reinitialize
150 GNUNET_PQ_reconnect (struct GNUNET_PQ_Context *db)
152 if (NULL != db->conn)
154 db->conn = PQconnectdb (db->config_str);
155 if ((NULL == db->conn) ||
156 (CONNECTION_OK != PQstatus (db->conn)))
158 GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
160 "Database connection to '%s' failed: %s\n",
163 PQerrorMessage (db->conn)
164 : "PQconnectdb returned NULL");
165 if (NULL != db->conn)
172 PQsetNoticeReceiver (db->conn,
173 &pq_notice_receiver_cb,
175 PQsetNoticeProcessor (db->conn,
176 &pq_notice_processor_cb,
178 if ( (NULL != db->es) &&
180 GNUNET_PQ_exec_statements (db,
187 if ( (NULL != db->ps) &&
189 GNUNET_PQ_prepare_statements (db,
200 * Connect to a postgres database using the configuration
201 * option "CONFIG" in @a section. Also ensures that the
202 * statements in @a es are executed whenever we (re)connect to the
203 * database, and that the prepared statements in @a ps are "ready".
205 * The caller MUST ensure that @a es and @a ps remain allocated and
206 * initialized in memory until #GNUNET_PQ_disconnect() is called,
207 * as they may be needed repeatedly and no copy will be made.
209 * @param cfg configuration
210 * @param section configuration section to use to get Postgres configuration options
211 * @param es #GNUNET_PQ_PREPARED_STATEMENT_END-terminated
212 * array of statements to execute upon EACH connection, can be NULL
213 * @param ps array of prepared statements to prepare, can be NULL
214 * @return the postgres handle, NULL on error
216 struct GNUNET_PQ_Context *
217 GNUNET_PQ_connect_with_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
219 const struct GNUNET_PQ_ExecuteStatement *es,
220 const struct GNUNET_PQ_PreparedStatement *ps)
222 struct GNUNET_PQ_Context *db;
226 GNUNET_CONFIGURATION_get_value_string (cfg,
231 db = GNUNET_PQ_connect (conninfo == NULL ? "" : conninfo,
234 GNUNET_free_non_null (conninfo);
240 * Disconnect from the database, destroying the prepared statements
241 * and releasing other associated resources.
243 * @param db database handle to disconnect (will be free'd)
246 GNUNET_PQ_disconnect (struct GNUNET_PQ_Context *db)
248 GNUNET_free_non_null (db->es);
249 GNUNET_free_non_null (db->ps);
255 /* end of pq/pq_connect.c */