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