diff options
-rw-r--r-- | src/include/taler_pq_lib.h | 134 | ||||
-rw-r--r-- | src/pq/db_pq.c | 199 | ||||
-rw-r--r-- | src/pq/pq_helper.c | 146 |
3 files changed, 462 insertions, 17 deletions
diff --git a/src/include/taler_pq_lib.h b/src/include/taler_pq_lib.h index d030d9b74..6199444e1 100644 --- a/src/include/taler_pq_lib.h +++ b/src/include/taler_pq_lib.h @@ -75,8 +75,27 @@ enum TALER_PQ_QueryFormat * We have an absolute time. * Data points to a `struct GNUNET_TIME_Absolute`, size is only used to check. */ - TALER_PQ_QF_TIME_ABSOLUTE + TALER_PQ_QF_TIME_ABSOLUTE, + /** + * We expect an uint16_t (in host byte order). + */ + TALER_PQ_QF_UINT16, + + /** + * We expect an uint32_t (in host byte order). + */ + TALER_PQ_QF_UINT32, + + /** + * We expect an uint64_t (in host byte order). + */ + TALER_PQ_QF_UINT64, + + /** + * We expect a JSON object (json_t). + */ + TALER_PQ_QF_JSON }; @@ -132,7 +151,7 @@ struct TALER_PQ_QueryParam * Generate query parameter for a currency, consisting of the three * components "value", "fraction" and "currency" in this order. The * types must be a 64-bit integer, 32-bit integer and a - * TALER_CURRENCY_LEN-sized BLOB/VARCHAR respectively. + * #TALER_CURRENCY_LEN-sized BLOB/VARCHAR respectively. * * @param x pointer to the query parameter to pass */ @@ -144,7 +163,7 @@ TALER_PQ_query_param_amount_nbo(const struct TALER_AmountNBO *x); * Generate query parameter for a currency, consisting of the three * components "value", "fraction" and "currency" in this order. The * types must be a 64-bit integer, 32-bit integer and a - * TALER_CURRENCY_LEN-sized BLOB/VARCHAR respectively. + * #TALER_CURRENCY_LEN-sized BLOB/VARCHAR respectively. * * @param x pointer to the query parameter to pass */ @@ -183,6 +202,43 @@ TALER_PQ_query_param_absolute_time(const struct GNUNET_TIME_Absolute *x); /** + * Generate query parameter for an uint16_t in host byte order. + * + * @param x pointer to the query parameter to pass + */ +struct TALER_PQ_QueryParam +TALER_PQ_query_param_uint16 (const uint16_t *x); + + +/** + * Generate query parameter for an uint32_t in host byte order. + * + * @param x pointer to the query parameter to pass + */ +struct TALER_PQ_QueryParam +TALER_PQ_query_param_uint32 (const uint32_t *x); + + +/** + * Generate query parameter for an uint16_t in host byte order. + * + * @param x pointer to the query parameter to pass + */ +struct TALER_PQ_QueryParam +TALER_PQ_query_param_uint64 (const uint64_t *x); + + +/** + * Generate query parameter for a JSON object (stored as a string + * in the DB). + * + * @param x pointer to the json object to pass + */ +struct TALER_PQ_QueryParam +TALER_PQ_query_param_json (const json_t *x); + + +/** * Different formats of results that can be extracted. */ enum TALER_PQ_ResultFormat @@ -231,7 +287,27 @@ enum TALER_PQ_ResultFormat * We expect an absolute time. * Data points to a `struct GNUNET_TIME_Absolute`, size is only used for checking. */ - TALER_PQ_RF_TIME_ABSOLUTE + TALER_PQ_RF_TIME_ABSOLUTE, + + /** + * We expect an uint16_t (in host byte order). + */ + TALER_PQ_RF_UINT16, + + /** + * We expect an uint32_t (in host byte order). + */ + TALER_PQ_RF_UINT32, + + /** + * We expect an uint64_t (in host byte order). + */ + TALER_PQ_RF_UINT64, + + /** + * We expect a JSON object (json_t). + */ + TALER_PQ_RF_JSON }; @@ -375,6 +451,54 @@ TALER_PQ_result_spec_absolute_time (const char *name, /** + * uint16_t expected. + * + * @param name name of the field in the table + * @param[out] u16 where to store the result + * @return array entry for the result specification to use + */ +struct TALER_PQ_ResultSpec +TALER_PQ_result_spec_uint16 (const char *name, + uint16_t *u16); + + +/** + * uint32_t expected. + * + * @param name name of the field in the table + * @param[out] u32 where to store the result + * @return array entry for the result specification to use + */ +struct TALER_PQ_ResultSpec +TALER_PQ_result_spec_uint32 (const char *name, + uint16_t *u32); + + +/** + * uint64_t expected. + * + * @param name name of the field in the table + * @param[out] u64 where to store the result + * @return array entry for the result specification to use + */ +struct TALER_PQ_ResultSpec +TALER_PQ_result_spec_uint64 (const char *name, + uint64_t *u64); + + +/** + * json_t expected. + * + * @param name name of the field in the table + * @param[out] jp where to store the result + * @return array entry for the result specification to use + */ +struct TALER_PQ_ResultSpec +TALER_PQ_result_spec_json (const char *name, + json_t **jp); + + +/** * Execute a prepared statement. * * @param db_conn database connection @@ -390,7 +514,7 @@ TALER_PQ_exec_prepared (PGconn *db_conn, /** * Extract results from a query result according to the given specification. - * If colums are NULL, the destination is not modified, and GNUNET_NO + * If colums are NULL, the destination is not modified, and #GNUNET_NO * is returned. * * @param result result to process diff --git a/src/pq/db_pq.c b/src/pq/db_pq.c index a718c805f..693da2f35 100644 --- a/src/pq/db_pq.c +++ b/src/pq/db_pq.c @@ -61,6 +61,10 @@ TALER_PQ_exec_prepared (PGconn *db_conn, case TALER_PQ_QF_RSA_PUBLIC_KEY: case TALER_PQ_QF_RSA_SIGNATURE: case TALER_PQ_QF_TIME_ABSOLUTE: + case TALER_PQ_QF_UINT16: + case TALER_PQ_QF_UINT32: + case TALER_PQ_QF_UINT64: + case TALER_PQ_QF_JSON: len++; break; default: @@ -175,7 +179,7 @@ TALER_PQ_exec_prepared (PGconn *db_conn, { const struct GNUNET_TIME_Absolute *at_hbo = x->data; struct GNUNET_TIME_AbsoluteNBO *at_nbo; - + at_nbo = GNUNET_new (struct GNUNET_TIME_AbsoluteNBO); scratch[soff++] = at_nbo; *at_nbo = GNUNET_TIME_absolute_hton (*at_hbo); @@ -185,6 +189,61 @@ TALER_PQ_exec_prepared (PGconn *db_conn, off++; } break; + case TALER_PQ_QF_UINT16: + { + const uint16_t *u_hbo = x->data; + uint16_t *u_nbo; + + u_nbo = GNUNET_new (uint16_t); + scratch[soff++] = u_nbo; + *u_nbo = htons (*u_hbo); + param_values[off] = (void *) u_nbo; + param_lengths[off] = sizeof (uint16_t); + param_formats[off] = 1; + off++; + } + break; + case TALER_PQ_QF_UINT32: + { + const uint32_t *u_hbo = x->data; + uint32_t *u_nbo; + + u_nbo = GNUNET_new (uint32_t); + scratch[soff++] = u_nbo; + *u_nbo = htonl (*u_hbo); + param_values[off] = (void *) u_nbo; + param_lengths[off] = sizeof (uint32_t); + param_formats[off] = 1; + off++; + } + break; + case TALER_PQ_QF_UINT64: + { + const uint64_t *u_hbo = x->data; + uint64_t *u_nbo; + + u_nbo = GNUNET_new (uint64_t); + scratch[soff++] = u_nbo; + *u_nbo = GNUNET_htonll (*u_hbo); + param_values[off] = (void *) u_nbo; + param_lengths[off] = sizeof (uint64_t); + param_formats[off] = 1; + off++; + } + break; + case TALER_PQ_QF_JSON: + { + const json_t *json = x->data; + char *str; + + str = json_dumps (json, JSON_COMPACT); + scratch[soff++] = str; + param_values[off] = (void *) str; + param_lengths[off] = strlen (str); + param_formats[off] = 1; + off++; + } + break; default: /* format not supported */ GNUNET_assert (0); @@ -538,7 +597,145 @@ TALER_PQ_extract_result (PGresult *result, *dst = GNUNET_TIME_absolute_ntoh (*res); break; } + case TALER_PQ_RF_UINT16: + { + uint16_t *dst = spec->dst; + const uint16_t *res; + int fnum; + + fnum = PQfnumber (result, + spec->fname); + if (fnum < 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Field `%s' does not exist in result\n", + spec->fname); + return GNUNET_SYSERR; + } + if (PQgetisnull (result, + row, + fnum)) + { + had_null = GNUNET_YES; + continue; + } + GNUNET_assert (NULL != dst); + GNUNET_assert (sizeof (uint16_t) == + spec->dst_size); + res = (uint16_t *) PQgetvalue (result, + row, + fnum); + *dst = ntohs (*res); + break; + } + case TALER_PQ_RF_UINT32: + { + uint32_t *dst = spec->dst; + const uint32_t *res; + int fnum; + + fnum = PQfnumber (result, + spec->fname); + if (fnum < 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Field `%s' does not exist in result\n", + spec->fname); + return GNUNET_SYSERR; + } + if (PQgetisnull (result, + row, + fnum)) + { + had_null = GNUNET_YES; + continue; + } + GNUNET_assert (NULL != dst); + GNUNET_assert (sizeof (uint32_t) == + spec->dst_size); + res = (uint32_t *) PQgetvalue (result, + row, + fnum); + *dst = ntohl (*res); + break; + } + case TALER_PQ_RF_UINT64: + { + uint64_t *dst = spec->dst; + const uint64_t *res; + int fnum; + + fnum = PQfnumber (result, + spec->fname); + if (fnum < 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Field `%s' does not exist in result\n", + spec->fname); + return GNUNET_SYSERR; + } + if (PQgetisnull (result, + row, + fnum)) + { + had_null = GNUNET_YES; + continue; + } + GNUNET_assert (NULL != dst); + GNUNET_assert (sizeof (uint64_t) == + spec->dst_size); + res = (uint64_t *) PQgetvalue (result, + row, + fnum); + *dst = GNUNET_ntohll (*res); + break; + } + case TALER_PQ_RF_JSON: + { + json_t **dst = spec->dst; + char *res; + int fnum; + json_error_t json_error; + size_t slen; + fnum = PQfnumber (result, + spec->fname); + if (fnum < 0) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Field `%s' does not exist in result\n", + spec->fname); + return GNUNET_SYSERR; + } + if (PQgetisnull (result, + row, + fnum)) + { + had_null = GNUNET_YES; + continue; + } + GNUNET_assert (NULL != dst); + GNUNET_break (0 == spec->dst_size); + slen = PQgetlength (result, + row, + fnum); + res = (char *) PQgetvalue (result, + row, + fnum); + *dst = json_loadb (res, + slen, + JSON_REJECT_DUPLICATES, + &json_error); + if (NULL == *dst) + { + TALER_json_warn (json_error); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to parse JSON result for field `%s'\n", + spec->fname); + return GNUNET_SYSERR; + } + break; + } default: GNUNET_assert (0); break; diff --git a/src/pq/pq_helper.c b/src/pq/pq_helper.c index 5da1ced41..01441dec3 100644 --- a/src/pq/pq_helper.c +++ b/src/pq/pq_helper.c @@ -15,7 +15,7 @@ */ /** * @file pq/pq_helper.c - * @brief functions to initialize parameter arrays + * @brief functions to initialize parameter arrays * @author Christian Grothoff */ #include "platform.h" @@ -39,7 +39,7 @@ TALER_PQ_query_param_amount_nbo (const struct TALER_AmountNBO *x) { TALER_PQ_QF_AMOUNT_NBO, x, sizeof (*x) }; return res; } - + /** * Generate query parameter for a currency, consisting of the three @@ -108,6 +108,63 @@ TALER_PQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x) /** + * Generate query parameter for an uint16_t in host byte order. + * + * @param x pointer to the query parameter to pass + */ +struct TALER_PQ_QueryParam +TALER_PQ_query_param_uint16 (const uint16_t *x) +{ + struct TALER_PQ_QueryParam res = + { TALER_PQ_QF_UINT16, x, sizeof (*x) }; + return res; +} + + +/** + * Generate query parameter for an uint32_t in host byte order. + * + * @param x pointer to the query parameter to pass + */ +struct TALER_PQ_QueryParam +TALER_PQ_query_param_uint32 (const uint32_t *x) +{ + struct TALER_PQ_QueryParam res = + { TALER_PQ_QF_UINT32, x, sizeof (*x) }; + return res; +} + + +/** + * Generate query parameter for an uint16_t in host byte order. + * + * @param x pointer to the query parameter to pass + */ +struct TALER_PQ_QueryParam +TALER_PQ_query_param_uint64 (const uint64_t *x) +{ + struct TALER_PQ_QueryParam res = + { TALER_PQ_QF_UINT64, x, sizeof (*x) }; + return res; +} + + +/** + * Generate query parameter for a JSON object (stored as a string + * in the DB). + * + * @param x pointer to the json object to pass + */ +struct TALER_PQ_QueryParam +TALER_PQ_query_param_json (const json_t *x) +{ + struct TALER_PQ_QueryParam res = + { TALER_PQ_QF_JSON, x, 0 }; + return res; +} + + +/** * Variable-size result expected. * * @param name name of the field in the table @@ -120,7 +177,7 @@ TALER_PQ_result_spec_variable_size (const char *name, void **dst, size_t *sptr) { - struct TALER_PQ_ResultSpec res = + struct TALER_PQ_ResultSpec res = { TALER_PQ_RF_VARSIZE_BLOB, (void *) (dst), 0, name, sptr }; return res; } @@ -137,7 +194,7 @@ struct TALER_PQ_ResultSpec TALER_PQ_result_spec_amount_nbo (const char *name, struct TALER_AmountNBO *amount) { - struct TALER_PQ_ResultSpec res = + struct TALER_PQ_ResultSpec res = {TALER_PQ_RF_AMOUNT_NBO, (void *) amount, sizeof (*amount), name, NULL }; return res; } @@ -154,7 +211,7 @@ struct TALER_PQ_ResultSpec TALER_PQ_result_spec_amount (const char *name, struct TALER_Amount *amount) { - struct TALER_PQ_ResultSpec res = + struct TALER_PQ_ResultSpec res = {TALER_PQ_RF_AMOUNT, (void *) amount, sizeof (*amount), name, NULL }; return res; } @@ -171,11 +228,11 @@ struct TALER_PQ_ResultSpec TALER_PQ_result_spec_rsa_public_key (const char *name, struct GNUNET_CRYPTO_rsa_PublicKey **rsa) { - struct TALER_PQ_ResultSpec res = + struct TALER_PQ_ResultSpec res = {TALER_PQ_RF_RSA_PUBLIC_KEY, (void *) rsa, 0, name, NULL }; return res; } - + /** * RSA signature expected. @@ -188,12 +245,12 @@ struct TALER_PQ_ResultSpec TALER_PQ_result_spec_rsa_signature (const char *name, struct GNUNET_CRYPTO_rsa_Signature **sig) { - struct TALER_PQ_ResultSpec res = + struct TALER_PQ_ResultSpec res = {TALER_PQ_RF_RSA_SIGNATURE, (void *) sig, 0, (name), NULL }; return res; } - + /** * Absolute time expected. * @@ -205,10 +262,77 @@ struct TALER_PQ_ResultSpec TALER_PQ_result_spec_absolute_time (const char *name, struct GNUNET_TIME_Absolute *at) { - struct TALER_PQ_ResultSpec res = + struct TALER_PQ_ResultSpec res = {TALER_PQ_RF_TIME_ABSOLUTE, (void *) at, sizeof (*at), (name), NULL }; return res; } - + + +/** + * uint16_t expected. + * + * @param name name of the field in the table + * @param[out] u16 where to store the result + * @return array entry for the result specification to use + */ +struct TALER_PQ_ResultSpec +TALER_PQ_result_spec_uint16 (const char *name, + uint16_t *u16) +{ + struct TALER_PQ_ResultSpec res = + {TALER_PQ_RF_UINT16, (void *) u16, sizeof (*u16), (name), NULL }; + return res; +} + + +/** + * uint32_t expected. + * + * @param name name of the field in the table + * @param[out] u32 where to store the result + * @return array entry for the result specification to use + */ +struct TALER_PQ_ResultSpec +TALER_PQ_result_spec_uint32 (const char *name, + uint16_t *u32) +{ + struct TALER_PQ_ResultSpec res = + {TALER_PQ_RF_UINT32, (void *) u32, sizeof (*u32), (name), NULL }; + return res; +} + + +/** + * uint64_t expected. + * + * @param name name of the field in the table + * @param[out] u64 where to store the result + * @return array entry for the result specification to use + */ +struct TALER_PQ_ResultSpec +TALER_PQ_result_spec_uint64 (const char *name, + uint64_t *u64) +{ + struct TALER_PQ_ResultSpec res = + {TALER_PQ_RF_UINT64, (void *) u64, sizeof (*u64), (name), NULL }; + return res; +} + + +/** + * json_t expected. + * + * @param name name of the field in the table + * @param[out] jp where to store the result + * @return array entry for the result specification to use + */ +struct TALER_PQ_ResultSpec +TALER_PQ_result_spec_json (const char *name, + json_t **jp) +{ + struct TALER_PQ_ResultSpec res = + {TALER_PQ_RF_JSON, (void *) jp, 0, (name), NULL }; + return res; +} /* end of pq_helper.c */ |