aboutsummaryrefslogtreecommitdiff
path: root/src/pq/pq.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pq/pq.c')
-rw-r--r--src/pq/pq.c169
1 files changed, 169 insertions, 0 deletions
diff --git a/src/pq/pq.c b/src/pq/pq.c
new file mode 100644
index 000000000..fe796044e
--- /dev/null
+++ b/src/pq/pq.c
@@ -0,0 +1,169 @@
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 under the
6 terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 3, or (at your option) any later version.
8
9 GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License along with
14 GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16/**
17 * @file pq/pq.c
18 * @brief helper functions for libpq (PostGres) interactions
19 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
20 * @author Florian Dold
21 * @author Christian Grothoff
22 */
23#include "platform.h"
24#include <gnunet/gnunet_util_lib.h>
25#include "gnunet_pq_lib.h"
26
27
28/**
29 * Execute a prepared statement.
30 *
31 * @param db_conn database connection
32 * @param name name of the prepared statement
33 * @param params parameters to the statement
34 * @return postgres result
35 */
36PGresult *
37GNUNET_PQ_exec_prepared (PGconn *db_conn,
38 const char *name,
39 const struct GNUNET_PQ_QueryParam *params)
40{
41 unsigned int len;
42 unsigned int i;
43
44 /* count the number of parameters */
45 len = 0;
46 for (i=0;0 != params[i].num_params;i++)
47 len += params[i].num_params;
48
49 /* new scope to allow stack allocation without alloca */
50 {
51 /* Scratch buffer for temporary storage */
52 void *scratch[len];
53 /* Parameter array we are building for the query */
54 void *param_values[len];
55 int param_lengths[len];
56 int param_formats[len];
57 unsigned int off;
58 /* How many entries in the scratch buffer are in use? */
59 unsigned int soff;
60 PGresult *res;
61 int ret;
62
63 off = 0;
64 soff = 0;
65 for (i=0;0 != params[i].num_params;i++)
66 {
67 const struct GNUNET_PQ_QueryParam *x = &params[i];
68
69 ret = x->conv (x->conv_cls,
70 x->data,
71 x->size,
72 &param_values[off],
73 &param_lengths[off],
74 &param_formats[off],
75 x->num_params,
76 &scratch[soff],
77 len - soff);
78 if (ret < 0)
79 {
80 for (off = 0; off < soff; off++)
81 GNUNET_free (scratch[off]);
82 return NULL;
83 }
84 soff += ret;
85 off += x->num_params;
86 }
87 GNUNET_assert (off == len);
88 res = PQexecPrepared (db_conn,
89 name,
90 len,
91 (const char **) param_values,
92 param_lengths,
93 param_formats,
94 1);
95 for (off = 0; off < soff; off++)
96 GNUNET_free (scratch[off]);
97 return res;
98 }
99}
100
101
102/**
103 * Free all memory that was allocated in @a rs during
104 * #GNUNET_PQ_extract_result().
105 *
106 * @param rs reult specification to clean up
107 */
108void
109GNUNET_PQ_cleanup_result (struct GNUNET_PQ_ResultSpec *rs)
110{
111 unsigned int i;
112
113 for (i=0; NULL != rs[i].conv; i++)
114 if (NULL != rs[i].cleaner)
115 rs[i].cleaner (rs[i].cls,
116 rs[i].dst);
117}
118
119
120/**
121 * Extract results from a query result according to the given
122 * specification. If colums are NULL, the destination is not
123 * modified, and #GNUNET_NO is returned.
124 *
125 * @param result result to process
126 * @param[in,out] rs result specification to extract for
127 * @param row row from the result to extract
128 * @return
129 * #GNUNET_YES if all results could be extracted
130 * #GNUNET_NO if at least one result was NULL
131 * #GNUNET_SYSERR if a result was invalid (non-existing field)
132 */
133int
134GNUNET_PQ_extract_result (PGresult *result,
135 struct GNUNET_PQ_ResultSpec *rs,
136 int row)
137{
138 unsigned int i;
139 int had_null = GNUNET_NO;
140 int ret;
141
142 for (i=0; NULL != rs[i].conv; i++)
143 {
144 struct GNUNET_PQ_ResultSpec *spec;
145
146 spec = &rs[i];
147 ret = spec->conv (spec->cls,
148 result,
149 row,
150 spec->fname,
151 &spec->dst_size,
152 spec->dst);
153 if (GNUNET_SYSERR == ret)
154 return GNUNET_SYSERR;
155 if (GNUNET_NO == ret)
156 {
157 had_null = GNUNET_YES;
158 continue;
159 }
160 if (NULL != spec->result_size)
161 *spec->result_size = spec->dst_size;
162 }
163 if (GNUNET_YES == had_null)
164 return GNUNET_NO;
165 return GNUNET_OK;
166}
167
168
169/* end of pq/pq.c */