summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-10-25 22:32:14 +0100
committerChristian Grothoff <christian@grothoff.org>2020-10-25 22:32:14 +0100
commitf7c320990c64ec5f29dc87340c24d5d9ebf7a835 (patch)
tree543a72c6a80ca898dfb83922e5635644c3a736e6
parentd8cf5cbfc9862d9187d9b15d12f7be523b757791 (diff)
implement #6524
-rw-r--r--src/include/gnunet_pq_lib.h55
-rw-r--r--src/pq/pq.c45
-rw-r--r--src/pq/pq_query_helper.c126
-rw-r--r--src/pq/pq_result_helper.c101
-rw-r--r--src/pq/test_pq.c17
5 files changed, 163 insertions, 181 deletions
diff --git a/src/include/gnunet_pq_lib.h b/src/include/gnunet_pq_lib.h
index ca549f77c..de717526c 100644
--- a/src/include/gnunet_pq_lib.h
+++ b/src/include/gnunet_pq_lib.h
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- Copyright (C) 2016, 2017 GNUnet e.V.
+ Copyright (C) 2016, 2017, 2020 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -87,6 +87,7 @@ struct GNUNET_PQ_QueryParam
* Number of parameters eaten by this operation.
*/
unsigned int num_params;
+
};
@@ -100,20 +101,32 @@ struct GNUNET_PQ_QueryParam
/**
+ * Generate query parameter to create a NULL value.
+ *
+ * @return query parameter to use to insert NULL into DB
+ */
+struct GNUNET_PQ_QueryParam
+GNUNET_PQ_query_param_null (void);
+
+
+/**
* Generate query parameter for a buffer @a ptr of
* @a ptr_size bytes.
*
* @param ptr pointer to the query parameter to pass
* @oaran ptr_size number of bytes in @a ptr
+ * @return query parameter to use
*/
struct GNUNET_PQ_QueryParam
-GNUNET_PQ_query_param_fixed_size (const void *ptr, size_t ptr_size);
+GNUNET_PQ_query_param_fixed_size (const void *ptr,
+ size_t ptr_size);
/**
* Generate query parameter for a string.
*
* @param ptr pointer to the string query parameter to pass
+ * @return query parameter to use
*/
struct GNUNET_PQ_QueryParam
GNUNET_PQ_query_param_string (const char *ptr);
@@ -124,6 +137,7 @@ GNUNET_PQ_query_param_string (const char *ptr);
* by variable type.
*
* @param x pointer to the query parameter to pass.
+ * @return query parameter to use
*/
#define GNUNET_PQ_query_param_auto_from_type(x) \
GNUNET_PQ_query_param_fixed_size ((x), sizeof(*(x)))
@@ -134,6 +148,7 @@ GNUNET_PQ_query_param_string (const char *ptr);
* database must contain a BLOB type in the respective position.
*
* @param x the query parameter to pass.
+ * @return query parameter to use
*/
struct GNUNET_PQ_QueryParam
GNUNET_PQ_query_param_rsa_public_key (
@@ -145,6 +160,7 @@ GNUNET_PQ_query_param_rsa_public_key (
* database must contain a BLOB type in the respective position.
*
* @param x the query parameter to pass
+ * @return query parameter to use
*/
struct GNUNET_PQ_QueryParam
GNUNET_PQ_query_param_rsa_signature (
@@ -156,6 +172,7 @@ GNUNET_PQ_query_param_rsa_signature (
* The database must store a 64-bit integer.
*
* @param x pointer to the query parameter to pass
+ * @return query parameter to use
*/
struct GNUNET_PQ_QueryParam
GNUNET_PQ_query_param_relative_time (const struct GNUNET_TIME_Relative *x);
@@ -166,6 +183,7 @@ GNUNET_PQ_query_param_relative_time (const struct GNUNET_TIME_Relative *x);
* The database must store a 64-bit integer.
*
* @param x pointer to the query parameter to pass
+ * @return query parameter to use
*/
struct GNUNET_PQ_QueryParam
GNUNET_PQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x);
@@ -176,6 +194,7 @@ GNUNET_PQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x);
* The database must store a 64-bit integer.
*
* @param x pointer to the query parameter to pass
+ * @return query parameter to use
*/
struct GNUNET_PQ_QueryParam
GNUNET_PQ_query_param_absolute_time_nbo (
@@ -186,6 +205,7 @@ GNUNET_PQ_query_param_absolute_time_nbo (
* Generate query parameter for an uint16_t in host byte order.
*
* @param x pointer to the query parameter to pass
+ * @return query parameter to use
*/
struct GNUNET_PQ_QueryParam
GNUNET_PQ_query_param_uint16 (const uint16_t *x);
@@ -195,6 +215,7 @@ GNUNET_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
+ * @return query parameter to use
*/
struct GNUNET_PQ_QueryParam
GNUNET_PQ_query_param_uint32 (const uint32_t *x);
@@ -204,6 +225,7 @@ GNUNET_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
+ * @return query parameter to use
*/
struct GNUNET_PQ_QueryParam
GNUNET_PQ_query_param_uint64 (const uint64_t *x);
@@ -288,6 +310,20 @@ struct GNUNET_PQ_ResultSpec
* Where to store actual size of the result.
*/
size_t *result_size;
+
+ /**
+ * True if NULL is allowed for a value in the database.
+ */
+ bool is_nullable;
+
+ /**
+ * Points to a location where we should store
+ * "true" if the result found is NULL, and
+ * otherwise "false". Only used if @e is_nullable
+ * is true.
+ */
+ bool *is_null;
+
};
@@ -303,6 +339,21 @@ struct GNUNET_PQ_ResultSpec
/**
+ * Allow NULL value to be found in the database
+ * for the given value.
+ *
+ * @param rs result spec entry to modify
+ * @param[out] is_null location set to 'true' if the
+ * value was indeed NULL, set to 'false' if the
+ * value was non-NULL
+ * @return array entry for the result specification to use
+ */
+struct GNUNET_PQ_ResultSpec
+GNUNET_PQ_result_spec_allow_null (struct GNUNET_PQ_ResultSpec rs,
+ bool *is_null);
+
+
+/**
* Variable-size result expected.
*
* @param name name of the field in the table
diff --git a/src/pq/pq.c b/src/pq/pq.c
index eca097e58..e9c960e33 100644
--- a/src/pq/pq.c
+++ b/src/pq/pq.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- Copyright (C) 2014, 2015, 2016, 2017, 2019 GNUnet e.V.
+ Copyright (C) 2014, 2015, 2016, 2017, 2019, 2020 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -27,14 +27,7 @@
#include "platform.h"
#include "pq.h"
-/**
- * Execute a prepared statement.
- *
- * @param db database handle
- * @param name name of the prepared statement
- * @param params parameters to the statement
- * @return postgres result
- */
+
PGresult *
GNUNET_PQ_exec_prepared (struct GNUNET_PQ_Context *db,
const char *name,
@@ -120,12 +113,6 @@ GNUNET_PQ_exec_prepared (struct GNUNET_PQ_Context *db,
}
-/**
- * Free all memory that was allocated in @a rs during
- * #GNUNET_PQ_extract_result().
- *
- * @param rs reult specification to clean up
- */
void
GNUNET_PQ_cleanup_result (struct GNUNET_PQ_ResultSpec *rs)
{
@@ -136,17 +123,6 @@ GNUNET_PQ_cleanup_result (struct GNUNET_PQ_ResultSpec *rs)
}
-/**
- * Extract results from a query result according to the given
- * specification.
- *
- * @param result result to process
- * @param[in,out] rs result specification to extract for
- * @param row row from the result to extract
- * @return
- * #GNUNET_YES if all results could be extracted
- * #GNUNET_SYSERR if a result was invalid (non-existing field)
- */
int
GNUNET_PQ_extract_result (PGresult *result,
struct GNUNET_PQ_ResultSpec *rs,
@@ -160,6 +136,23 @@ GNUNET_PQ_extract_result (PGresult *result,
int ret;
spec = &rs[i];
+ if (spec->is_nullable)
+ {
+ int fnum;
+
+ fnum = PQfnumber (result,
+ spec->fname);
+ if (PQgetisnull (result,
+ row,
+ fnum))
+ {
+ if (NULL != spec->is_null)
+ *spec->is_null = true;
+ continue;
+ }
+ if (NULL != spec->is_null)
+ *spec->is_null = false;
+ }
ret = spec->conv (spec->cls,
result,
row,
diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c
index a36848f3a..cee84d203 100644
--- a/src/pq/pq_query_helper.c
+++ b/src/pq/pq_query_helper.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- Copyright (C) 2014, 2015, 2016 GNUnet e.V.
+ Copyright (C) 2014, 2015, 2016, 2020 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -42,6 +42,56 @@
* @return -1 on error, number of offsets used in @a scratch otherwise
*/
static int
+qconv_null (void *cls,
+ const void *data,
+ size_t data_len,
+ void *param_values[],
+ int param_lengths[],
+ int param_formats[],
+ unsigned int param_length,
+ void *scratch[],
+ unsigned int scratch_length)
+{
+ (void) scratch;
+ (void) scratch_length;
+ (void) data;
+ (void) data_len;
+ GNUNET_break (NULL == cls);
+ if (1 != param_length)
+ return -1;
+ param_values[0] = NULL;
+ param_lengths[0] = 0;
+ param_formats[0] = 1;
+ return 0;
+}
+
+
+struct GNUNET_PQ_QueryParam
+GNUNET_PQ_query_param_null (void)
+{
+ struct GNUNET_PQ_QueryParam res = {
+ &qconv_null, NULL, NULL, 0, 1
+ };
+
+ return res;
+}
+
+
+/**
+ * Function called to convert input argument into SQL parameters.
+ *
+ * @param cls closure
+ * @param data pointer to input argument
+ * @param data_len number of bytes in @a data (if applicable)
+ * @param[out] param_values SQL data to set
+ * @param[out] param_lengths SQL length data to set
+ * @param[out] param_formats SQL format data to set
+ * @param param_length number of entries available in the @a param_values, @a param_lengths and @a param_formats arrays
+ * @param[out] scratch buffer for dynamic allocations (to be done via #GNUNET_malloc()
+ * @param scratch_length number of entries left in @a scratch
+ * @return -1 on error, number of offsets used in @a scratch otherwise
+ */
+static int
qconv_fixed (void *cls,
const void *data,
size_t data_len,
@@ -64,33 +114,23 @@ qconv_fixed (void *cls,
}
-/**
- * Generate query parameter for a buffer @a ptr of
- * @a ptr_size bytes.
- *
- * @param ptr pointer to the query parameter to pass
- * @oaran ptr_size number of bytes in @a ptr
- */
struct GNUNET_PQ_QueryParam
GNUNET_PQ_query_param_fixed_size (const void *ptr,
size_t ptr_size)
{
- struct GNUNET_PQ_QueryParam res =
- { &qconv_fixed, NULL, ptr, ptr_size, 1 };
+ struct GNUNET_PQ_QueryParam res = {
+ &qconv_fixed, NULL, ptr, ptr_size, 1
+ };
return res;
}
-/**
- * Generate query parameter for a string.
- *
- * @param ptr pointer to the string query parameter to pass
- */
struct GNUNET_PQ_QueryParam
GNUNET_PQ_query_param_string (const char *ptr)
{
- return GNUNET_PQ_query_param_fixed_size (ptr, strlen (ptr));
+ return GNUNET_PQ_query_param_fixed_size (ptr,
+ strlen (ptr));
}
@@ -137,11 +177,6 @@ qconv_uint16 (void *cls,
}
-/**
- * Generate query parameter for an uint16_t in host byte order.
- *
- * @param x pointer to the query parameter to pass
- */
struct GNUNET_PQ_QueryParam
GNUNET_PQ_query_param_uint16 (const uint16_t *x)
{
@@ -195,11 +230,6 @@ qconv_uint32 (void *cls,
}
-/**
- * Generate query parameter for an uint32_t in host byte order.
- *
- * @param x pointer to the query parameter to pass
- */
struct GNUNET_PQ_QueryParam
GNUNET_PQ_query_param_uint32 (const uint32_t *x)
{
@@ -253,11 +283,6 @@ qconv_uint64 (void *cls,
}
-/**
- * Generate query parameter for an uint64_t in host byte order.
- *
- * @param x pointer to the query parameter to pass
- */
struct GNUNET_PQ_QueryParam
GNUNET_PQ_query_param_uint64 (const uint64_t *x)
{
@@ -310,13 +335,6 @@ qconv_rsa_public_key (void *cls,
}
-/**
- * Generate query parameter for an RSA public key. The
- * database must contain a BLOB type in the respective position.
- *
- * @param x the query parameter to pass
- * @return array entry for the query parameters to use
- */
struct GNUNET_PQ_QueryParam
GNUNET_PQ_query_param_rsa_public_key (const struct
GNUNET_CRYPTO_RsaPublicKey *x)
@@ -370,13 +388,6 @@ qconv_rsa_signature (void *cls,
}
-/**
- * Generate query parameter for an RSA signature. The
- * database must contain a BLOB type in the respective position.
- *
- * @param x the query parameter to pass
- * @return array entry for the query parameters to use
- */
struct GNUNET_PQ_QueryParam
GNUNET_PQ_query_param_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *x)
{
@@ -432,13 +443,6 @@ qconv_rel_time (void *cls,
}
-/**
- * Generate query parameter for a relative time value.
- * The database must store a 64-bit integer.
- *
- * @param x pointer to the query parameter to pass
- * @return array entry for the query parameters to use
- */
struct GNUNET_PQ_QueryParam
GNUNET_PQ_query_param_relative_time (const struct GNUNET_TIME_Relative *x)
{
@@ -494,29 +498,17 @@ qconv_abs_time (void *cls,
}
-/**
- * Generate query parameter for an absolute time value.
- * The database must store a 64-bit integer.
- *
- * @param x pointer to the query parameter to pass
- * @return array entry for the query parameters to use
- */
struct GNUNET_PQ_QueryParam
GNUNET_PQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x)
{
- struct GNUNET_PQ_QueryParam res =
- { &qconv_abs_time, NULL, x, sizeof(*x), 1 };
+ struct GNUNET_PQ_QueryParam res = {
+ &qconv_abs_time, NULL, x, sizeof(*x), 1
+ };
return res;
}
-/**
- * Generate query parameter for an absolute time value.
- * The database must store a 64-bit integer.
- *
- * @param x pointer to the query parameter to pass
- */
struct GNUNET_PQ_QueryParam
GNUNET_PQ_query_param_absolute_time_nbo (const struct
GNUNET_TIME_AbsoluteNBO *x)
diff --git a/src/pq/pq_result_helper.c b/src/pq/pq_result_helper.c
index f764593b0..546822e45 100644
--- a/src/pq/pq_result_helper.c
+++ b/src/pq/pq_result_helper.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- Copyright (C) 2014, 2015, 2016 GNUnet e.V.
+ Copyright (C) 2014, 2015, 2016, 2020 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
@@ -27,6 +27,19 @@
#include "gnunet_pq_lib.h"
+struct GNUNET_PQ_ResultSpec
+GNUNET_PQ_result_spec_allow_null (struct GNUNET_PQ_ResultSpec rs,
+ bool *is_null)
+{
+ struct GNUNET_PQ_ResultSpec rsr;
+
+ rsr = rs;
+ rsr.is_nullable = true;
+ rsr.is_null = is_null;
+ return rsr;
+}
+
+
/**
* Function called to clean up memory allocated
* by a #GNUNET_PQ_ResultConverter.
@@ -112,14 +125,6 @@ extract_varsize_blob (void *cls,
}
-/**
- * Variable-size result expected.
- *
- * @param name name of the field in the table
- * @param[out] dst where to store the result, allocated
- * @param[out] sptr where to store the size of @a dst
- * @return array entry for the result specification to use
- */
struct GNUNET_PQ_ResultSpec
GNUNET_PQ_result_spec_variable_size (const char *name,
void **dst,
@@ -196,14 +201,6 @@ extract_fixed_blob (void *cls,
}
-/**
- * Fixed-size result expected.
- *
- * @param name name of the field in the table
- * @param[out] dst where to store the result
- * @param dst_size number of bytes in @a dst
- * @return array entry for the result specification to use
- */
struct GNUNET_PQ_ResultSpec
GNUNET_PQ_result_spec_fixed_size (const char *name,
void *dst,
@@ -301,13 +298,6 @@ clean_rsa_public_key (void *cls,
}
-/**
- * RSA public key expected.
- *
- * @param name name of the field in the table
- * @param[out] rsa where to store the result
- * @return array entry for the result specification to use
- */
struct GNUNET_PQ_ResultSpec
GNUNET_PQ_result_spec_rsa_public_key (const char *name,
struct GNUNET_CRYPTO_RsaPublicKey **rsa)
@@ -405,13 +395,6 @@ clean_rsa_signature (void *cls,
}
-/**
- * RSA signature expected.
- *
- * @param name name of the field in the table
- * @param[out] sig where to store the result;
- * @return array entry for the result specification to use
- */
struct GNUNET_PQ_ResultSpec
GNUNET_PQ_result_spec_rsa_signature (const char *name,
struct GNUNET_CRYPTO_RsaSignature **sig)
@@ -509,13 +492,6 @@ clean_string (void *cls,
}
-/**
- * 0-terminated string expected.
- *
- * @param name name of the field in the table
- * @param[out] dst where to store the result, allocated
- * @return array entry for the result specification to use
- */
struct GNUNET_PQ_ResultSpec
GNUNET_PQ_result_spec_string (const char *name,
char **dst)
@@ -595,13 +571,6 @@ extract_rel_time (void *cls,
}
-/**
- * Relative time expected.
- *
- * @param name name of the field in the table
- * @param[out] at where to store the result
- * @return array entry for the result specification to use
- */
struct GNUNET_PQ_ResultSpec
GNUNET_PQ_result_spec_relative_time (const char *name,
struct GNUNET_TIME_Relative *rt)
@@ -685,13 +654,6 @@ extract_abs_time (void *cls,
}
-/**
- * Absolute time expected.
- *
- * @param name name of the field in the table
- * @param[out] at where to store the result
- * @return array entry for the result specification to use
- */
struct GNUNET_PQ_ResultSpec
GNUNET_PQ_result_spec_absolute_time (const char *name,
struct GNUNET_TIME_Absolute *at)
@@ -706,13 +668,6 @@ GNUNET_PQ_result_spec_absolute_time (const char *name,
}
-/**
- * Absolute time in network byte order expected.
- *
- * @param name name of the field in the table
- * @param[out] at where to store the result
- * @return array entry for the result specification to use
- */
struct GNUNET_PQ_ResultSpec
GNUNET_PQ_result_spec_absolute_time_nbo (const char *name,
struct GNUNET_TIME_AbsoluteNBO *at)
@@ -786,13 +741,6 @@ extract_uint16 (void *cls,
}
-/**
- * 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 GNUNET_PQ_ResultSpec
GNUNET_PQ_result_spec_uint16 (const char *name,
uint16_t *u16)
@@ -869,13 +817,6 @@ extract_uint32 (void *cls,
}
-/**
- * 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 GNUNET_PQ_ResultSpec
GNUNET_PQ_result_spec_uint32 (const char *name,
uint32_t *u32)
@@ -952,22 +893,16 @@ extract_uint64 (void *cls,
}
-/**
- * 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 GNUNET_PQ_ResultSpec
GNUNET_PQ_result_spec_uint64 (const char *name,
uint64_t *u64)
{
- struct GNUNET_PQ_ResultSpec res =
- { &extract_uint64,
+ struct GNUNET_PQ_ResultSpec res = {
+ &extract_uint64,
NULL,
NULL,
- (void *) u64, sizeof(*u64), (name), NULL };
+ (void *) u64, sizeof(*u64), (name), NULL
+ };
return res;
}
diff --git a/src/pq/test_pq.c b/src/pq/test_pq.c
index b09354af8..e588da45d 100644
--- a/src/pq/test_pq.c
+++ b/src/pq/test_pq.c
@@ -47,10 +47,11 @@ postgres_prepare (struct GNUNET_PQ_Context *db)
",u16"
",u32"
",u64"
+ ",unn"
") VALUES "
"($1, $2, $3, $4, $5, $6,"
- "$7, $8, $9);",
- 9),
+ "$7, $8, $9, $10);",
+ 10),
GNUNET_PQ_make_prepare ("test_select",
"SELECT"
" pub"
@@ -62,6 +63,7 @@ postgres_prepare (struct GNUNET_PQ_Context *db)
",u16"
",u32"
",u64"
+ ",unn"
" FROM test_pq"
" ORDER BY abs_time DESC "
" LIMIT 1;",
@@ -106,7 +108,8 @@ run_queries (struct GNUNET_PQ_Context *db)
uint32_t u322;
uint64_t u64;
uint64_t u642;
-
+ uint64_t uzzz = 42;
+
priv = GNUNET_CRYPTO_rsa_private_key_create (1024);
pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
memset (&hmsg, 42, sizeof(hmsg));
@@ -127,11 +130,13 @@ run_queries (struct GNUNET_PQ_Context *db)
GNUNET_PQ_query_param_uint16 (&u16),
GNUNET_PQ_query_param_uint32 (&u32),
GNUNET_PQ_query_param_uint64 (&u64),
+ GNUNET_PQ_query_param_null (),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_QueryParam params_select[] = {
GNUNET_PQ_query_param_end
};
+ bool got_null = false;
struct GNUNET_PQ_ResultSpec results_select[] = {
GNUNET_PQ_result_spec_rsa_public_key ("pub", &pub2),
GNUNET_PQ_result_spec_rsa_signature ("sig", &sig2),
@@ -142,6 +147,9 @@ run_queries (struct GNUNET_PQ_Context *db)
GNUNET_PQ_result_spec_uint16 ("u16", &u162),
GNUNET_PQ_result_spec_uint32 ("u32", &u322),
GNUNET_PQ_result_spec_uint64 ("u64", &u642),
+ GNUNET_PQ_result_spec_allow_null (
+ GNUNET_PQ_result_spec_uint64 ("unn", &uzzz),
+ &got_null),
GNUNET_PQ_result_spec_end
};
@@ -197,6 +205,8 @@ run_queries (struct GNUNET_PQ_Context *db)
GNUNET_break (16 == u162);
GNUNET_break (32 == u322);
GNUNET_break (64 == u642);
+ GNUNET_break (42 == uzzz);
+ GNUNET_break (got_null);
GNUNET_PQ_cleanup_result (results_select);
PQclear (result);
}
@@ -225,6 +235,7 @@ main (int argc,
",u16 INT2 NOT NULL"
",u32 INT4 NOT NULL"
",u64 INT8 NOT NULL"
+ ",unn INT8"
")"),
GNUNET_PQ_EXECUTE_STATEMENT_END
};