implementing pq APIs for #3827, not yet tested or used through

This commit is contained in:
Christian Grothoff 2015-06-10 16:31:29 +02:00
parent d45534c574
commit aef3b7c350
3 changed files with 462 additions and 17 deletions

View File

@ -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
*/
@ -182,6 +201,43 @@ struct TALER_PQ_QueryParam
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.
*/
@ -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
};
@ -374,6 +450,54 @@ TALER_PQ_result_spec_absolute_time (const char *name,
struct GNUNET_TIME_Absolute *at);
/**
* 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.
*
@ -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

View File

@ -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:
@ -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;

View File

@ -107,6 +107,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.
*
@ -211,4 +268,71 @@ 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)
{
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 */