remove CYGWIN codeblocks, drop vendored Windows openvpn, drop win32 specific files.
[oweals/gnunet.git] / src / pq / pq.c
1 /*
2    This file is part of GNUnet
3    Copyright (C) 2014, 2015, 2016 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.c
22  * @brief helper functions for libpq (PostGres) interactions
23  * @author Sree Harsha Totakura <sreeharsha@totakura.in>
24  * @author Florian Dold
25  * @author Christian Grothoff
26  */
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_pq_lib.h"
30
31
32 /**
33  * Execute a prepared statement.
34  *
35  * @param db_conn database connection
36  * @param name name of the prepared statement
37  * @param params parameters to the statement
38  * @return postgres result
39  */
40 PGresult *
41 GNUNET_PQ_exec_prepared(PGconn *db_conn,
42                         const char *name,
43                         const struct GNUNET_PQ_QueryParam *params)
44 {
45   unsigned int len;
46   unsigned int i;
47
48   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
49              "Running prepared statement `%s' on %p\n",
50              name,
51              db_conn);
52   /* count the number of parameters */
53   len = 0;
54   for (i = 0; 0 != params[i].num_params; i++)
55     len += params[i].num_params;
56
57   /* new scope to allow stack allocation without alloca */
58   {
59     /* Scratch buffer for temporary storage */
60     void *scratch[len];
61     /* Parameter array we are building for the query */
62     void *param_values[len];
63     int param_lengths[len];
64     int param_formats[len];
65     unsigned int off;
66     /* How many entries in the scratch buffer are in use? */
67     unsigned int soff;
68     PGresult *res;
69     int ret;
70
71     off = 0;
72     soff = 0;
73     for (i = 0; 0 != params[i].num_params; i++)
74       {
75         const struct GNUNET_PQ_QueryParam *x = &params[i];
76
77         ret = x->conv(x->conv_cls,
78                       x->data,
79                       x->size,
80                       &param_values[off],
81                       &param_lengths[off],
82                       &param_formats[off],
83                       x->num_params,
84                       &scratch[soff],
85                       len - soff);
86         if (ret < 0)
87           {
88             for (off = 0; off < soff; off++)
89               GNUNET_free(scratch[off]);
90             return NULL;
91           }
92         soff += ret;
93         off += x->num_params;
94       }
95     GNUNET_assert(off == len);
96     GNUNET_log_from(GNUNET_ERROR_TYPE_DEBUG,
97                     "pq",
98                     "Executing prepared SQL statement `%s'\n",
99                     name);
100     res = PQexecPrepared(db_conn,
101                          name,
102                          len,
103                          (const char **)param_values,
104                          param_lengths,
105                          param_formats,
106                          1);
107     for (off = 0; off < soff; off++)
108       GNUNET_free(scratch[off]);
109     return res;
110   }
111 }
112
113
114 /**
115  * Free all memory that was allocated in @a rs during
116  * #GNUNET_PQ_extract_result().
117  *
118  * @param rs reult specification to clean up
119  */
120 void
121 GNUNET_PQ_cleanup_result(struct GNUNET_PQ_ResultSpec *rs)
122 {
123   unsigned int i;
124
125   for (i = 0; NULL != rs[i].conv; i++)
126     if (NULL != rs[i].cleaner)
127       rs[i].cleaner(rs[i].cls,
128                     rs[i].dst);
129 }
130
131
132 /**
133  * Extract results from a query result according to the given
134  * specification.
135  *
136  * @param result result to process
137  * @param[in,out] rs result specification to extract for
138  * @param row row from the result to extract
139  * @return
140  *   #GNUNET_YES if all results could be extracted
141  *   #GNUNET_SYSERR if a result was invalid (non-existing field)
142  */
143 int
144 GNUNET_PQ_extract_result(PGresult *result,
145                          struct GNUNET_PQ_ResultSpec *rs,
146                          int row)
147 {
148   unsigned int i;
149   int ret;
150
151   for (i = 0; NULL != rs[i].conv; i++)
152     {
153       struct GNUNET_PQ_ResultSpec *spec;
154
155       spec = &rs[i];
156       ret = spec->conv(spec->cls,
157                        result,
158                        row,
159                        spec->fname,
160                        &spec->dst_size,
161                        spec->dst);
162       if (GNUNET_OK != ret)
163         {
164           GNUNET_PQ_cleanup_result(rs);
165           return GNUNET_SYSERR;
166         }
167       if (NULL != spec->result_size)
168         *spec->result_size = spec->dst_size;
169     }
170   return GNUNET_OK;
171 }
172
173
174 /* end of pq/pq.c */