From 571d43cef3732ed6f491d91a9e767a80008edeb1 Mon Sep 17 00:00:00 2001 From: Özgür Kesim Date: Thu, 27 Jul 2023 23:57:07 +0200 Subject: [WiP] added TALER_AMOUNT type to Postgres - first in age_withdraw - Added a type TALER_AMOUNT (val INT8, frac INT4) to Postgres. - Added PLSQL functions/procedures - amount_normalize(a) - amount_add(a, b) - amount_left_minus_right(l, r, diff, ok bool) - Added PQ-helper functions - TALER_PQ_query_param_amount_tuple() - TALER_PQ_result_spec_amount_tuple() - In table 'age_withdraw', changed fields 'amount_with_fee_val' and '..._frac' into single field 'amount_with_fee' be of type TALER_AMOUNT - Changed functions/stored procedures 'do_age_withdraw' and 'get_age_withdraw' to use new APIs. => make check runs through without errors, age-withdraw and -reveal test passes. --- src/pq/pq_result_helper.c | 145 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 142 insertions(+), 3 deletions(-) (limited to 'src/pq/pq_result_helper.c') diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c index 0a734bbc..3ef2e71f 100644 --- a/src/pq/pq_result_helper.c +++ b/src/pq/pq_result_helper.c @@ -264,6 +264,145 @@ TALER_PQ_result_spec_amount (const char *name, } +/** + * Extract an amount from a tuple from a Postgres database @a result at row @a row. + * + * @param cls closure, a `const char *` giving the currency + * @param result where to extract data from + * @param row row to extract data from + * @param fname name (or prefix) of the fields to extract from + * @param[in,out] dst_size where to store size of result, may be NULL + * @param[out] dst where to store the result + * @return + * #GNUNET_YES if all results could be extracted + * #GNUNET_NO if at least one result was NULL + * #GNUNET_SYSERR if a result was invalid (non-existing field) + */ +static enum GNUNET_GenericReturnValue +extract_amount_tuple (void *cls, + PGresult *result, + int row, + const char *fname, + size_t *dst_size, + void *dst) +{ + struct TALER_Amount *r_amount = dst; + const char *currency = cls; + int col; + int len; + + if (sizeof (struct TALER_Amount) != *dst_size) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + + /* Set return value to invalid in case we don't finish */ + memset (r_amount, + 0, + sizeof (struct TALER_Amount)); + col = PQfnumber (result, + fname); + if (col < 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Field `%s' does not exist in result\n", + fname); + return GNUNET_SYSERR; + } + if (PQgetisnull (result, + row, + col)) + { + return GNUNET_NO; + } + + /* Parse the tuple */ + { + char *in; + uint32_t num; + struct TALER_PQ_Amount_P ap; + int size; + const static int expected_size = sizeof(uint32_t) /* length */ + + sizeof(struct TALER_PQ_Amount_P); + + size = PQgetlength (result, + row, + col); + + if (expected_size != size) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Incorrect size of binary field `%s' (got %d, expected %d)\n", + fname, + size, + expected_size); + return GNUNET_SYSERR; + } + + in = PQgetvalue (result, + row, + col); + + num = ntohl (*(uint32_t *) in); + if (2 != num) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Incorrect number of elements in tuple-field `%s'\n", + fname); + return GNUNET_SYSERR; + } + in += sizeof(uint32_t); + ap = *(struct TALER_PQ_Amount_P *) in; + + /* TODO[oec]: OID-checks? */ + + r_amount->value = GNUNET_ntohll (ap.v); + r_amount->fraction = ntohl (ap.f); + } + + if (r_amount->value >= TALER_AMOUNT_MAX_VALUE) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Value in field `%s' exceeds legal range\n", + fname); + return GNUNET_SYSERR; + } + if (r_amount->fraction >= TALER_AMOUNT_FRAC_BASE) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Fraction in field `%s' exceeds legal range\n", + fname); + return GNUNET_SYSERR; + } + + len = GNUNET_MIN (TALER_CURRENCY_LEN - 1, + strlen (currency)); + + GNUNET_memcpy (r_amount->currency, + currency, + len); + return GNUNET_OK; +} + + +struct GNUNET_PQ_ResultSpec +TALER_PQ_result_spec_amount_tuple (const char *name, + const char *currency, + struct TALER_Amount *amount) +{ + struct GNUNET_PQ_ResultSpec res = { + .conv = &extract_amount_tuple, + .cls = (void *) currency, + .dst = (void *) amount, + .dst_size = sizeof (*amount), + .fname = name + }; + + return res; +} + + /** * Extract data from a Postgres database @a result at row @a row. * @@ -1027,7 +1166,7 @@ extract_array_generic ( int data_sz; char *data; void *out = NULL; - struct TALER_PQ_ArrayHeader header; + struct TALER_PQ_ArrayHeader_P header; int col_num; GNUNET_assert (NULL != dst); @@ -1053,8 +1192,8 @@ extract_array_generic ( FAIL_IF (NULL == data); { - struct TALER_PQ_ArrayHeader *h = - (struct TALER_PQ_ArrayHeader *) data; + struct TALER_PQ_ArrayHeader_P *h = + (struct TALER_PQ_ArrayHeader_P *) data; header.ndim = ntohl (h->ndim); header.has_null = ntohl (h->has_null); -- cgit v1.2.3