gnunet

Main GNUnet Logic
Log | Files | Refs | Submodules | README | LICENSE

commit 4b6fa1ca917f8bb0401d2cb7f1c919dbbcf3f123
parent f533d1dfd5425c567725f636e80b45b6ae9dec13
Author: Özgür Kesim <oec-taler@kesim.org>
Date:   Sun, 14 May 2023 17:29:04 +0200

pq: API for array types extended for time

NEWS: API for array types extended for times

New API's:

  - for continuous arrays:
    - GNUNET_PQ_query_param_array_abs_time
    - GNUNET_PQ_query_param_array_rel_time
    - GNUNET_PQ_query_param_array_timestamp

  - for arrays of pointers:
    - GNUNET_PQ_query_param_array_ptrs_abs_time
    - GNUNET_PQ_query_param_array_ptrs_rel_time
    - GNUNET_PQ_query_param_array_ptrs_timestamp

Diffstat:
Msrc/include/gnunet_pq_lib.h | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/pq/pq_query_helper.c | 259+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Msrc/pq/test_pq.c | 23++++++++++++++++++++++-
3 files changed, 320 insertions(+), 39 deletions(-)

diff --git a/src/include/gnunet_pq_lib.h b/src/include/gnunet_pq_lib.h @@ -28,6 +28,7 @@ #include <libpq-fe.h> #include <stdint.h> +#include "gnunet_time_lib.h" #include "gnunet_util_lib.h" #include "gnunet_db_lib.h" @@ -377,8 +378,84 @@ GNUNET_PQ_query_param_array_ptrs_string ( #define GNUNET_PQ_query_param_auto_from_type(x) \ GNUNET_PQ_query_param_fixed_size ((x), sizeof(*(x))) +/** + * Generate query parameter for an array of absolute time stamps (continuous) + * + * @param num Number of elements in @a elements + * @param elements Array of @a num absolute timestamps + * @return query parameter to use + */ +struct GNUNET_PQ_QueryParam +GNUNET_PQ_query_param_array_abs_time ( + unsigned int num, + const struct GNUNET_TIME_Absolute *elements, + const struct GNUNET_PQ_Context *db); + +/** + * Generate query parameter for an array of absolute time stamps (pointers) + * + * @param num Number of elements in @a elements + * @param elements Array of @a num pointers to absolute timestamps + * @return query parameter to use + */ +struct GNUNET_PQ_QueryParam +GNUNET_PQ_query_param_array_ptrs_abs_time ( + unsigned int num, + const struct GNUNET_TIME_Absolute *elements[], + const struct GNUNET_PQ_Context *db); + +/** + * Generate query parameter for an array of relative time stamps (continuous) + * + * @param num Number of elements in @a elements + * @param elements Array of @a num relative timestamps + * @return query parameter to use + */ +struct GNUNET_PQ_QueryParam +GNUNET_PQ_query_param_array_rel_time ( + unsigned int num, + const struct GNUNET_TIME_Relative *elements, + const struct GNUNET_PQ_Context *db); /** + * Generate query parameter for an array of relative time stamps (pointers) + * + * @param num Number of elements in @a elements + * @param elements Array of @a num pointers to relative timestamps + * @return query parameter to use + */ +struct GNUNET_PQ_QueryParam +GNUNET_PQ_query_param_array_ptrs_rel_time ( + unsigned int num, + const struct GNUNET_TIME_Relative *elements[], + const struct GNUNET_PQ_Context *db); + +/** + * Generate query parameter for an array of time stamps (continuous) + * + * @param num Number of elements in @a elements + * @param elements Array of @a num timestamps + * @return query parameter to use + */ +struct GNUNET_PQ_QueryParam +GNUNET_PQ_query_param_array_timestamp ( + unsigned int num, + const struct GNUNET_TIME_Timestamp *elements, + const struct GNUNET_PQ_Context *db); + +/** + * Generate query parameter for an array of time stamps (pointers) + * + * @param num Number of elements in @a elements + * @param elements Array of @a num pointers to relative timestamps + * @return query parameter to use + */ +struct GNUNET_PQ_QueryParam +GNUNET_PQ_query_param_array_ptrs_timestamp ( + unsigned int num, + const struct GNUNET_TIME_Timestamp *elements[], + const struct GNUNET_PQ_Context *db); +/** * Generate query parameter for an RSA public key. The * database must contain a BLOB type in the respective position. * diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c @@ -24,6 +24,7 @@ */ #include "gnunet_common.h" #include "gnunet_pq_lib.h" +#include "gnunet_time_lib.h" #include "platform.h" #include "pq.h" @@ -589,6 +590,24 @@ struct pq_array_header } __attribute__((packed)); /** + * Internal types that are supported as array types. + */ + +enum array_types +{ + array_of_bool, + array_of_uint16, + array_of_uint32, + array_of_uint64, + array_of_byte, /* buffers of (char *), (void *), ... */ + array_of_string, /* NULL-terminated (char *) */ + array_of_abs_time, + array_of_rel_time, + array_of_timestamp, + array_of_MAX, /* must be last */ +}; + +/** * Closure for the array type handlers. * * May contain sizes information for the data, given (and handled) by the @@ -620,7 +639,7 @@ struct qconv_array_cls /** * Type of the array elements */ - enum GNUNET_PQ_DataTypes typ; + enum array_types typ; /** * Oid of the array elements @@ -674,7 +693,6 @@ qconv_array ( size_t total_size; const size_t *sizes; bool same_sized; - bool is_string_array; size_t *string_lengths = NULL; void *elements = NULL; bool noerror = true; @@ -687,7 +705,6 @@ qconv_array ( sizes = meta->sizes; same_sized = (0 != meta->same_size); - is_string_array = (GNUNET_PQ_DATATYPE_VARCHAR == meta->typ); #define RETURN_UNLESS(cond) \ do { \ @@ -724,7 +741,7 @@ qconv_array ( else /* sizes are different per element */ { /* for an array of strings we need to get their length's first */ - if (is_string_array) + if (array_of_string == meta->typ) { string_lengths = GNUNET_new_array (num, size_t); @@ -787,37 +804,38 @@ qconv_array ( switch (meta->typ) { - case GNUNET_PQ_DATATYPE_INT2: + case array_of_bool: + { + GNUNET_assert (sizeof(bool) == sz); + GNUNET_memcpy (out, in, sz); + in += sz; + break; + } + case array_of_uint16: { GNUNET_assert (sizeof(uint16_t) == sz); *(uint16_t *) out = htons (*(uint16_t *) in); in += sz; break; } - case GNUNET_PQ_DATATYPE_INT4: + case array_of_uint32: { GNUNET_assert (sizeof(uint32_t) == sz); *(uint32_t *) out = htonl (*(uint32_t *) in); in += sz; break; } - case GNUNET_PQ_DATATYPE_INT8: + case array_of_uint64: { GNUNET_assert (sizeof(uint64_t) == sz); *(uint64_t *) out = GNUNET_htonll (*(uint64_t *) in); in += sz; break; } - case GNUNET_PQ_DATATYPE_BOOL: - { - GNUNET_assert (sizeof(bool) == sz); - GNUNET_memcpy (out, in, sz); - in += sz; - break; - } - case GNUNET_PQ_DATATYPE_BYTEA: + case array_of_byte: { const void *ptr; + if (meta->continuous) { ptr = in; @@ -829,7 +847,7 @@ qconv_array ( GNUNET_memcpy (out, ptr, sz); break; } - case GNUNET_PQ_DATATYPE_VARCHAR: + case array_of_string: { const void *ptr; if (meta->continuous) @@ -843,6 +861,63 @@ qconv_array ( GNUNET_memcpy (out, ptr, sz); break; } + case array_of_abs_time: + { + const struct GNUNET_TIME_Absolute *abs; + + if (meta->continuous) + { + abs = (const struct GNUNET_TIME_Absolute *) in; + in += sz; + } + else + abs = ((const struct GNUNET_TIME_Absolute **) data)[i]; + + if (abs->abs_value_us > INT64_MAX) + *(uint64_t *) out = GNUNET_htonll (INT64_MAX); + else + *(uint64_t *) out = GNUNET_htonll (abs->abs_value_us); + + break; + } + case array_of_rel_time: + { + const struct GNUNET_TIME_Relative *rel; + + if (meta->continuous) + { + rel = (const struct GNUNET_TIME_Relative *) in; + in += sz; + } + else + rel = ((const struct GNUNET_TIME_Relative **) data)[i]; + + if (rel->rel_value_us > INT64_MAX) + *(uint64_t *) out = GNUNET_htonll (INT64_MAX); + else + *(uint64_t *) out = GNUNET_htonll (rel->rel_value_us); + + break; + } + case array_of_timestamp: + { + const struct GNUNET_TIME_Timestamp *ts; + + if (meta->continuous) + { + ts = (const struct GNUNET_TIME_Timestamp *) in; + in += sz; + } + else + ts = ((const struct GNUNET_TIME_Timestamp **) data)[i]; + + if (ts->abs_time.abs_value_us > INT64_MAX) + *(uint64_t *) out = GNUNET_htonll (INT64_MAX); + else + *(uint64_t *) out = GNUNET_htonll (ts->abs_time.abs_value_us); + + break; + } default: { GNUNET_assert (0); @@ -868,14 +943,26 @@ qconv_array ( } +/** + * Function to genreate a typ specific query parameter and corresponding closure + * + * @param num Number of elements in @a elements + * @param continuous If true, @a elements is an continuous array of data + * @param elements Array of @a num elements, either continuous or pointers + * @param sizes Array of @a num sizes, one per element, may be NULL + * @param same_size If not 0, all elements in @a elements have this size + * @param typ Supported internal type of each element in @a elements + * @param oid Oid of the type to be used in Postgres + * @return Query parameter + */ static struct GNUNET_PQ_QueryParam query_param_array_generic ( unsigned int num, + bool continuous, const void *elements, const size_t *sizes, - bool continuous, size_t same_size, - enum GNUNET_PQ_DataTypes typ, + enum array_types typ, Oid oid) { struct qconv_array_cls *meta = GNUNET_new (struct qconv_array_cls); @@ -905,11 +992,11 @@ GNUNET_PQ_query_param_array_bool ( const struct GNUNET_PQ_Context *db) { return query_param_array_generic (num, + true, elements, NULL, - true, sizeof(bool), - GNUNET_PQ_DATATYPE_BOOL, + array_of_bool, db->oids[GNUNET_PQ_DATATYPE_BOOL]); } @@ -921,11 +1008,11 @@ GNUNET_PQ_query_param_array_uint16 ( const struct GNUNET_PQ_Context *db) { return query_param_array_generic (num, + true, elements, NULL, - true, sizeof(uint16_t), - GNUNET_PQ_DATATYPE_INT2, + array_of_uint16, db->oids[GNUNET_PQ_DATATYPE_INT2]); } @@ -937,11 +1024,11 @@ GNUNET_PQ_query_param_array_uint32 ( const struct GNUNET_PQ_Context *db) { return query_param_array_generic (num, + true, elements, NULL, - true, sizeof(uint32_t), - GNUNET_PQ_DATATYPE_INT4, + array_of_uint32, db->oids[GNUNET_PQ_DATATYPE_INT4]); } @@ -953,11 +1040,11 @@ GNUNET_PQ_query_param_array_uint64 ( const struct GNUNET_PQ_Context *db) { return query_param_array_generic (num, + true, elements, NULL, - true, sizeof(uint64_t), - GNUNET_PQ_DATATYPE_INT8, + array_of_uint64, db->oids[GNUNET_PQ_DATATYPE_INT8]); } @@ -970,11 +1057,11 @@ GNUNET_PQ_query_param_array_bytes ( const struct GNUNET_PQ_Context *db) { return query_param_array_generic (num, + true, elements, sizes, - true, 0, - GNUNET_PQ_DATATYPE_BYTEA, + array_of_byte, db->oids[GNUNET_PQ_DATATYPE_BYTEA]); } @@ -987,11 +1074,11 @@ GNUNET_PQ_query_param_array_ptrs_bytes ( const struct GNUNET_PQ_Context *db) { return query_param_array_generic (num, + false, elements, sizes, - false, 0, - GNUNET_PQ_DATATYPE_BYTEA, + array_of_byte, db->oids[GNUNET_PQ_DATATYPE_BYTEA]); } @@ -1004,11 +1091,11 @@ GNUNET_PQ_query_param_array_bytes_same_size ( const struct GNUNET_PQ_Context *db) { return query_param_array_generic (num, + true, elements, NULL, - true, same_size, - GNUNET_PQ_DATATYPE_BYTEA, + array_of_byte, db->oids[GNUNET_PQ_DATATYPE_BYTEA]); } @@ -1021,11 +1108,11 @@ GNUNET_PQ_query_param_array_ptrs_bytes_same_size ( const struct GNUNET_PQ_Context *db) { return query_param_array_generic (num, + false, elements, NULL, - false, same_size, - GNUNET_PQ_DATATYPE_BYTEA, + array_of_byte, db->oids[GNUNET_PQ_DATATYPE_BYTEA]); } @@ -1037,11 +1124,11 @@ GNUNET_PQ_query_param_array_string ( const struct GNUNET_PQ_Context *db) { return query_param_array_generic (num, + true, elements, NULL, - true, 0, - GNUNET_PQ_DATATYPE_VARCHAR, + array_of_string, db->oids[GNUNET_PQ_DATATYPE_VARCHAR]); } @@ -1053,13 +1140,109 @@ GNUNET_PQ_query_param_array_ptrs_string ( const struct GNUNET_PQ_Context *db) { return query_param_array_generic (num, + false, elements, NULL, - false, 0, - GNUNET_PQ_DATATYPE_VARCHAR, + array_of_string, db->oids[GNUNET_PQ_DATATYPE_VARCHAR]); } +struct GNUNET_PQ_QueryParam +GNUNET_PQ_query_param_array_abs_time ( + unsigned int num, + const struct GNUNET_TIME_Absolute *elements, + const struct GNUNET_PQ_Context *db) +{ + return query_param_array_generic (num, + true, + elements, + NULL, + sizeof(struct GNUNET_TIME_Absolute), + array_of_abs_time, + db->oids[GNUNET_PQ_DATATYPE_INT8]); +} + + +struct GNUNET_PQ_QueryParam +GNUNET_PQ_query_param_array_ptrs_abs_time ( + unsigned int num, + const struct GNUNET_TIME_Absolute *elements[], + const struct GNUNET_PQ_Context *db) +{ + return query_param_array_generic (num, + false, + elements, + NULL, + sizeof(struct GNUNET_TIME_Absolute), + array_of_abs_time, + db->oids[GNUNET_PQ_DATATYPE_INT8]); +} + + +struct GNUNET_PQ_QueryParam +GNUNET_PQ_query_param_array_rel_time ( + unsigned int num, + const struct GNUNET_TIME_Relative *elements, + const struct GNUNET_PQ_Context *db) +{ + return query_param_array_generic (num, + true, + elements, + NULL, + sizeof(struct GNUNET_TIME_Relative), + array_of_abs_time, + db->oids[GNUNET_PQ_DATATYPE_INT8]); +} + + +struct GNUNET_PQ_QueryParam +GNUNET_PQ_query_param_array_ptrs_rel_time ( + unsigned int num, + const struct GNUNET_TIME_Relative *elements[], + const struct GNUNET_PQ_Context *db) +{ + return query_param_array_generic (num, + false, + elements, + NULL, + sizeof(struct GNUNET_TIME_Relative), + array_of_abs_time, + db->oids[GNUNET_PQ_DATATYPE_INT8]); +} + + +struct GNUNET_PQ_QueryParam +GNUNET_PQ_query_param_array_timestamp ( + unsigned int num, + const struct GNUNET_TIME_Timestamp *elements, + const struct GNUNET_PQ_Context *db) +{ + return query_param_array_generic (num, + true, + elements, + NULL, + sizeof(struct GNUNET_TIME_Timestamp), + array_of_timestamp, + db->oids[GNUNET_PQ_DATATYPE_INT8]); +} + + +struct GNUNET_PQ_QueryParam +GNUNET_PQ_query_param_array_ptrs_timestamp ( + unsigned int num, + const struct GNUNET_TIME_Timestamp *elements[], + const struct GNUNET_PQ_Context *db) +{ + return query_param_array_generic (num, + false, + elements, + NULL, + sizeof(struct GNUNET_TIME_Timestamp), + array_of_timestamp, + db->oids[GNUNET_PQ_DATATYPE_INT8]); +} + + /* end of pq_query_helper.c */ diff --git a/src/pq/test_pq.c b/src/pq/test_pq.c @@ -23,6 +23,7 @@ * @author Christian Grothoff <christian@grothoff.org> */ #include "gnunet_common.h" +#include "gnunet_time_lib.h" #include "platform.h" #include "pq.h" @@ -75,10 +76,14 @@ postgres_prepare (struct GNUNET_PQ_Context *db) ",arr_int8" ",arr_bytea" ",arr_varchar" + ",arr_abs_time" + ",arr_rel_time" + ",arr_timestamp" ") VALUES " "($1, $2, $3, $4, $5, $6," "$7, $8, $9, $10," - "$11, $12, $13, $14, $15, $16);"), + "$11, $12, $13, $14, $15, $16," + "$17, $18, $19);"), GNUNET_PQ_make_prepare ("test_select", "SELECT" " pub" @@ -97,6 +102,9 @@ postgres_prepare (struct GNUNET_PQ_Context *db) ",arr_int8" ",arr_bytea" ",arr_varchar" + ",arr_abs_time" + ",arr_rel_time" + ",arr_timestamp" " FROM test_pq" " ORDER BY abs_time DESC " " LIMIT 1;"), @@ -147,6 +155,13 @@ run_queries (struct GNUNET_PQ_Context *db) uint32_t ai4[3] = {42, 0x00010000, 0xFFFFFFFF}; uint64_t ai8[3] = {42, 0x0001000000000000, 0xFFFFFFFFFFFFFFFF}; const char *as[] = {"foo", "bar", "buz"}; + const struct GNUNET_TIME_Absolute ata[2] = {GNUNET_TIME_absolute_get (), + GNUNET_TIME_absolute_get ()}; + const struct GNUNET_TIME_Relative atr[2] = {GNUNET_TIME_relative_get_hour_ (), + GNUNET_TIME_relative_get_minute_ ()}; + const struct GNUNET_TIME_Timestamp ats[2] = {GNUNET_TIME_timestamp_get (), + GNUNET_TIME_timestamp_get ()}; + priv = GNUNET_CRYPTO_rsa_private_key_create (1024); pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv); @@ -184,6 +199,9 @@ run_queries (struct GNUNET_PQ_Context *db) sizeof(ahc[0]), db), GNUNET_PQ_query_param_array_ptrs_string (3, as, db), + GNUNET_PQ_query_param_array_abs_time (2, ata, db), + GNUNET_PQ_query_param_array_rel_time (2, atr, db), + GNUNET_PQ_query_param_array_timestamp (2, ats, db), GNUNET_PQ_query_param_end }; struct GNUNET_PQ_QueryParam params_select[] = { @@ -383,6 +401,9 @@ main (int argc, ",arr_int8 INT8[]" ",arr_bytea BYTEA[]" ",arr_varchar VARCHAR[]" + ",arr_abs_time INT8[]" + ",arr_rel_time INT8[]" + ",arr_timestamp INT8[]" ")"), GNUNET_PQ_EXECUTE_STATEMENT_END };