aboutsummaryrefslogtreecommitdiff
path: root/src/util/db.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/db.c')
-rw-r--r--src/util/db.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/src/util/db.c b/src/util/db.c
new file mode 100644
index 000000000..a0b234a06
--- /dev/null
+++ b/src/util/db.c
@@ -0,0 +1,196 @@
1/*
2 This file is part of TALER
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
5 TALER 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 TALER 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 TALER; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16
17
18/**
19 * @file util/db.c
20 * @brief helper functions for DB interactions
21 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
22 * @author Florian Dold
23 */
24
25#include "platform.h"
26#include <gnunet/gnunet_util_lib.h>
27#include "taler_db_lib.h"
28
29
30/**
31 * Execute a prepared statement.
32 */
33PGresult *
34TALER_DB_exec_prepared (PGconn *db_conn,
35 const char *name,
36 const struct TALER_DB_QueryParam *params)
37{
38 unsigned len;
39 unsigned i;
40
41 /* count the number of parameters */
42
43 {
44 const struct TALER_DB_QueryParam *x;
45 for (len = 0, x = params;
46 x->more;
47 len +=1, x += 1);
48 }
49
50 /* new scope to allow stack allocation without alloca */
51
52 {
53 void *param_values[len];
54 int param_lengths[len];
55 int param_formats[len];
56
57 for (i = 0; i < len; i += 1)
58 {
59 param_values[i] = (void *) params[i].data;
60 param_lengths[i] = params[i].size;
61 param_formats[i] = 1;
62 }
63 return PQexecPrepared (db_conn, name, len,
64 (const char **) param_values, param_lengths, param_formats, 1);
65 }
66}
67
68
69/**
70 * Extract results from a query result according to the given specification.
71 * If colums are NULL, the destination is not modified, and GNUNET_NO
72 * is returned.
73 *
74 * @return
75 * GNUNET_YES if all results could be extracted
76 * GNUNET_NO if at least one result was NULL
77 * GNUNET_SYSERR if a result was invalid (non-existing field)
78 */
79int
80TALER_DB_extract_result (PGresult *result,
81 struct TALER_DB_ResultSpec *rs,
82 int row)
83{
84 int had_null = GNUNET_NO;
85
86 for (; NULL != rs->fname; rs += 1)
87 {
88 int fnum;
89 fnum = PQfnumber (result, rs->fname);
90 if (fnum < 0)
91 {
92 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "field '%s' does not exist in result\n", rs->fname);
93 return GNUNET_SYSERR;
94 }
95
96 /* if a field is null, continue but
97 * remember that we now return a different result */
98
99 if (PQgetisnull (result, row, fnum))
100 {
101 had_null = GNUNET_YES;
102 continue;
103 }
104 const char *res;
105 if (rs->dst_size != PQgetlength (result, row, fnum))
106 {
107 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "field '%s' has wrong size (got %u, expected %u)\n",
108 rs->fname, (int) PQgetlength (result, row, fnum), (int) rs->dst_size);
109 return GNUNET_SYSERR;
110 }
111 res = PQgetvalue (result, row, fnum);
112 GNUNET_assert (NULL != res);
113 memcpy (rs->dst, res, rs->dst_size);
114 }
115 if (GNUNET_YES == had_null)
116 return GNUNET_NO;
117 return GNUNET_YES;
118}
119
120
121int
122TALER_DB_field_isnull (PGresult *result,
123 int row,
124 const char *fname)
125{
126 int fnum;
127 fnum = PQfnumber (result, fname);
128 GNUNET_assert (fnum >= 0);
129 if (PQgetisnull (result, row, fnum))
130 return GNUNET_YES;
131 return GNUNET_NO;
132}
133
134
135int
136TALER_DB_extract_amount_nbo (PGresult *result,
137 int row,
138 const char *val_name,
139 const char *frac_name,
140 const char *curr_name,
141 struct TALER_AmountNBO *r_amount_nbo)
142{
143 int val_num;
144 int frac_num;
145 int curr_num;
146 int len;
147
148 GNUNET_assert (NULL != strstr (val_name, "_val"));
149 GNUNET_assert (NULL != strstr (frac_name, "_frac"));
150 GNUNET_assert (NULL != strstr (curr_name, "_curr"));
151
152 val_num = PQfnumber (result, val_name);
153 GNUNET_assert (val_num >= 0);
154 frac_num = PQfnumber (result, frac_name);
155 GNUNET_assert (frac_num >= 0);
156 curr_num = PQfnumber (result, curr_name);
157 GNUNET_assert (curr_num >= 0);
158
159 r_amount_nbo->value = *(uint32_t *) PQgetvalue (result, row, val_num);
160 r_amount_nbo->fraction = *(uint32_t *) PQgetvalue (result, row, frac_num);
161 memset (r_amount_nbo->currency, 0, TALER_CURRENCY_LEN);
162 // FIXME: overflow?
163 len = PQgetlength (result, row, curr_num);
164 len = GNUNET_MIN (TALER_CURRENCY_LEN, len);
165 memcpy (r_amount_nbo->currency, PQgetvalue (result, row, curr_num), len);
166 r_amount_nbo->currency[TALER_CURRENCY_LEN - 1] = '\0';
167
168 return GNUNET_OK;
169}
170
171
172int
173TALER_DB_extract_amount (PGresult *result,
174 int row,
175 const char *val_name,
176 const char *frac_name,
177 const char *curr_name,
178 struct TALER_Amount *r_amount)
179{
180 struct TALER_AmountNBO amount_nbo;
181
182 (void)
183 TALER_DB_extract_amount_nbo (result,
184 row,
185 val_name,
186 frac_name,
187 curr_name,
188 &amount_nbo);
189 r_amount->value = ntohl (amount_nbo.value);
190 r_amount->fraction = ntohl (amount_nbo.fraction);
191 (void) strncpy (r_amount->currency, amount_nbo.currency, TALER_CURRENCY_LEN);
192
193 return GNUNET_OK;
194}
195
196/* end of util/db.c */