GNUnet  0.19.2
my.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2016, 2018 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  */
26 #include "platform.h"
27 #include <mysql/mysql.h>
28 #include "gnunet_mysql_compat.h"
29 #include "gnunet_my_lib.h"
30 
31 
42 int
45  struct GNUNET_MY_QueryParam *params)
46 {
47  const struct GNUNET_MY_QueryParam *p;
48  unsigned int num;
49  MYSQL_STMT *stmt;
50 
51  num = 0;
52  for (unsigned int i = 0; NULL != params[i].conv; i++)
53  num += params[i].num_params;
54  {
55  MYSQL_BIND qbind[num];
56  unsigned int off;
57 
58  memset (qbind,
59  0,
60  sizeof(qbind));
61  off = 0;
62  for (unsigned int i = 0; NULL != (p = &params[i])->conv; i++)
63  {
64  if (GNUNET_OK !=
65  p->conv (p->conv_cls,
66  p,
67  &qbind[off]))
68  {
70  "Conversion for MySQL query failed at offset %u\n",
71  i);
72  return GNUNET_SYSERR;
73  }
74  off += p->num_params;
75  }
77  if (mysql_stmt_bind_param (stmt,
78  qbind))
79  {
81  "my",
82  _ ("`%s' failed at %s:%d with error: %s\n"),
83  "mysql_stmt_bind_param",
84  __FILE__, __LINE__,
85  mysql_stmt_error (stmt));
87  return GNUNET_SYSERR;
88  }
89 
90  if (mysql_stmt_execute (stmt))
91  {
93  "my",
94  _ ("`%s' failed at %s:%d with error: %s\n"),
95  "mysql_stmt_execute", __FILE__, __LINE__,
96  mysql_stmt_error (stmt));
98  return GNUNET_SYSERR;
99  }
100  GNUNET_MY_cleanup_query (params,
101  qbind);
102  }
103  return GNUNET_OK;
104 }
105 
106 
114 void
116  MYSQL_BIND *qbind)
117 {
118  for (unsigned int i = 0; NULL != qp[i].conv; i++)
119  if (NULL != qp[i].cleaner)
120  qp[i].cleaner (qp[i].conv_cls,
121  &qbind[i]);
122 }
123 
124 
136 int
138  struct GNUNET_MY_ResultSpec *rs)
139 {
140  unsigned int num_fields;
141  int ret;
142  MYSQL_STMT *stmt;
143 
145  if (NULL == stmt)
146  {
147  GNUNET_break (0);
148  return GNUNET_SYSERR;
149  }
150  if (NULL == rs)
151  {
152  mysql_stmt_free_result (stmt);
153  return GNUNET_NO;
154  }
155 
156  num_fields = 0;
157  for (unsigned int i = 0; NULL != rs[i].pre_conv; i++)
158  num_fields += rs[i].num_fields;
159 
160  if (mysql_stmt_field_count (stmt) != num_fields)
161  {
163  "Number of fields mismatch between SQL result and result specification\n");
164  return GNUNET_SYSERR;
165  }
166 
167  {
168  MYSQL_BIND result[num_fields];
169  unsigned int field_off;
170 
171  memset (result, 0, sizeof(MYSQL_BIND) * num_fields);
172  field_off = 0;
173  for (unsigned int i = 0; NULL != rs[i].pre_conv; i++)
174  {
175  struct GNUNET_MY_ResultSpec *rp = &rs[i];
176 
177  if (GNUNET_OK !=
178  rp->pre_conv (rp->conv_cls,
179  rp,
180  stmt,
181  field_off,
182  &result[field_off]))
183 
184  {
186  "Pre-conversion for MySQL result failed at offset %u\n",
187  i);
188  return GNUNET_SYSERR;
189  }
190  field_off += rp->num_fields;
191  }
192 
193  if (mysql_stmt_bind_result (stmt, result))
194  {
196  "my",
197  _ ("%s failed at %s:%d with error: %s\n"),
198  "mysql_stmt_bind_result",
199  __FILE__, __LINE__,
200  mysql_stmt_error (stmt));
201  return GNUNET_SYSERR;
202  }
203 #if TEST_OPTIMIZATION
204  (void) mysql_stmt_store_result (stmt);
205 #endif
206  ret = mysql_stmt_fetch (stmt);
207  if (MYSQL_NO_DATA == ret)
208  {
209  mysql_stmt_free_result (stmt);
210  return GNUNET_NO;
211  }
212  if (1 == ret)
213  {
215  "my",
216  _ ("%s failed at %s:%d with error: %s\n"),
217  "mysql_stmt_fetch",
218  __FILE__, __LINE__,
219  mysql_stmt_error (stmt));
221  mysql_stmt_free_result (stmt);
222  return GNUNET_SYSERR;
223  }
224  field_off = 0;
225  for (unsigned int i = 0; NULL != rs[i].post_conv; i++)
226  {
227  struct GNUNET_MY_ResultSpec *rp = &rs[i];
228 
229  if (NULL != rp->post_conv)
230  if (GNUNET_OK !=
231  rp->post_conv (rp->conv_cls,
232  rp,
233  stmt,
234  field_off,
235  &result[field_off]))
236  {
238  "Post-conversion for MySQL result failed at offset %u\n",
239  i);
240  mysql_stmt_free_result (stmt);
241  for (unsigned int j = 0; j < i; j++)
242  if (NULL != rs[j].cleaner)
243  rs[j].cleaner (rs[j].conv_cls,
244  rs[j].dst);
245  return GNUNET_SYSERR;
246  }
247  field_off += rp->num_fields;
248  }
249  }
250  return GNUNET_OK;
251 }
252 
253 
260 void
262 {
263  for (unsigned int i = 0; NULL != rs[i].post_conv; i++)
264  if (NULL != rs[i].cleaner)
265  rs[i].cleaner (rs[i].conv_cls,
266  &rs[i]);
267 }
268 
269 
270 /* end of my.c */
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static struct SolverHandle * sh
static GstElement * conv
static char * rp
Relying party.
static struct GNUNET_TESTBED_Controller * mc
Handle to the master controller.
static int result
Global testing status.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
Helper library to access a MySQL database.
#define GNUNET_log(kind,...)
#define GNUNET_log_from(kind, comp,...)
@ GNUNET_OK
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_INFO
void GNUNET_MY_cleanup_query(struct GNUNET_MY_QueryParam *qp, MYSQL_BIND *qbind)
Free all memory that was allocated in qp during GNUNET_MY_exec_prepared().
Definition: my.c:115
void GNUNET_MY_cleanup_result(struct GNUNET_MY_ResultSpec *rs)
Free all memory that was allocated in rs during GNUNET_MY_extract_result().
Definition: my.c:261
MYSQL_STMT * GNUNET_MYSQL_statement_get_stmt(struct GNUNET_MYSQL_StatementHandle *sh)
Get internal handle for a prepared statement.
Definition: mysql.c:478
void GNUNET_MYSQL_statements_invalidate(struct GNUNET_MYSQL_Context *mc)
Close database connection and all prepared statements (we got a DB error).
Definition: mysql.c:342
int GNUNET_MY_exec_prepared(struct GNUNET_MYSQL_Context *mc, struct GNUNET_MYSQL_StatementHandle *sh, struct GNUNET_MY_QueryParam *params)
Run a prepared SELECT statement.
Definition: my.c:43
int GNUNET_MY_extract_result(struct GNUNET_MYSQL_StatementHandle *sh, struct GNUNET_MY_ResultSpec *rs)
Extract results from a query result according to the given specification.
Definition: my.c:137
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
Mysql context.
Definition: mysql.c:77
Handle for a prepared statement.
Definition: mysql.c:114
Information we pass to GNUNET_MY_exec_prepared() to initialize the arguments of the prepared statemen...
Definition: gnunet_my_lib.h:93
void * conv_cls
Closure for conv.
unsigned int num_params
Number of arguments the conv converter expects to initialize.
GNUNET_MY_QueryCleanup cleaner
Function to call for cleaning up the query.
GNUNET_MY_QueryConverter conv
Function to call for the type conversion.
Definition: gnunet_my_lib.h:97
Information we pass to GNUNET_MY_extract_result() to initialize the arguments of the prepared stateme...
void * conv_cls
Closure for conv.
GNUNET_MY_ResultConverter post_conv
Function to call for converting the result.
void * dst
Destination for the data.
GNUNET_MY_ResultConverter pre_conv
Function to call to initialize the MYSQL_BIND array.
GNUNET_MY_ResultCleanup cleaner
Function to call for cleaning up the result.