commit 17c852381a483b943273cdebbf48f23d2919c278
parent 9ff4a49c0c72c11218180f83930b3879e5022207
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date: Fri, 28 Jul 2023 17:52:29 +0200
Merge branch 'master' of git+ssh://git.gnunet.org/gnunet
NEWS: -
Diffstat:
3 files changed, 175 insertions(+), 41 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_common.h"
#include "gnunet_time_lib.h"
#include "gnunet_util_lib.h"
#include "gnunet_db_lib.h"
@@ -131,13 +132,13 @@ GNUNET_PQ_cleanup_query_params_closures (
* End of query parameter specification.
*/
#define GNUNET_PQ_query_param_end \
- { \
- .conv = NULL, \
- .conv_cls = NULL, \
- .data = NULL, \
- .size = 0, \
- .num_params = 0 \
- }
+ { \
+ .conv = NULL, \
+ .conv_cls = NULL, \
+ .data = NULL, \
+ .size = 0, \
+ .num_params = 0 \
+ }
/**
@@ -198,7 +199,7 @@ enum GNUNET_PQ_DataTypes
};
/**
- * Returns the oid for a given datatype
+ * Returns the oid for a given, basic datatype
*
* @param db The db-connection
* @param typ the Datatype
@@ -210,6 +211,38 @@ GNUNET_PQ_get_oid (
enum GNUNET_PQ_DataTypes typ);
/**
+ * Returns the oid for a given datatype by name.
+ *
+ * @param db The db-connection
+ * @param name The name of the datatype
+ * @param[out] oid The OID of the datatype.
+ * @return GNUNET_OK when the datatype was found, GNUNET_SYSERR otherwise
+ */
+enum GNUNET_GenericReturnValue
+GNUNET_PQ_get_oid_by_name (
+ struct GNUNET_PQ_Context *db,
+ const char *name,
+ Oid *oid);
+
+
+/**
+ * The header for a postgresql array in binary format. note that this a
+ * simplified special case of the general structure (which contains pointers),
+ * as we only support one-dimensional arrays.
+ *
+ * Note that all values must be in network-byte-order.
+ */
+struct GNUNET_PQ_ArrayHeader_P
+{
+ uint32_t ndim; /* number of dimensions. we only support ndim = 1 */
+ uint32_t has_null;
+ uint32_t oid; /* oid of the elements */
+ uint32_t dim; /* size of the array */
+ uint32_t lbound; /* index value of first element in the db (default: 1). */
+} __attribute__((packed));
+
+
+/**
* Generate query parameter for an array of bool in host byte order.
*
* @param num Number of elements in @a elements
@@ -312,10 +345,10 @@ GNUNET_PQ_query_param_array_bytes_same_size (
* @return query parameter to use
*/
#define GNUNET_PQ_query_param_array_auto_from_type(num, elements, db) \
- GNUNET_PQ_query_param_array_bytes_same_size ((num), \
- (elements), \
- sizeof(*(elements)), \
- (db))
+ GNUNET_PQ_query_param_array_bytes_same_size ((num), \
+ (elements), \
+ sizeof(*(elements)), \
+ (db))
/**
* Generate query parameter for an array of pointers to buffers @a elements,
@@ -345,10 +378,10 @@ GNUNET_PQ_query_param_array_ptrs_bytes_same_size (
* @return query parameter to use
*/
#define GNUNET_PQ_query_param_array_ptrs_auto_from_type(num, elements, db) \
- GNUNET_PQ_query_param_array_ptrs_bytes_same_size ((num), \
- (elements), \
- sizeof(*(elements[0])), \
- (db))
+ GNUNET_PQ_query_param_array_ptrs_bytes_same_size ((num), \
+ (elements), \
+ sizeof(*(elements[0])), \
+ (db))
/**
@@ -388,7 +421,7 @@ GNUNET_PQ_query_param_array_ptrs_string (
* @return query parameter to use
*/
#define GNUNET_PQ_query_param_auto_from_type(x) \
- GNUNET_PQ_query_param_fixed_size ((x), sizeof(*(x)))
+ GNUNET_PQ_query_param_fixed_size ((x), sizeof(*(x)))
/**
* Generate query parameter for an array of absolute time stamps (continuous)
@@ -679,17 +712,17 @@ struct GNUNET_PQ_ResultSpec
* @return array last entry for the result specification to use
*/
#define GNUNET_PQ_result_spec_end \
- { \
- .conv = NULL, \
- .cleaner = NULL, \
- .cls = NULL, \
- .dst = NULL, \
- .dst_size = 0, \
- .fname = NULL, \
- .result_size = NULL, \
- .is_nullable = false, \
- .is_null = NULL \
- }
+ { \
+ .conv = NULL, \
+ .cleaner = NULL, \
+ .cls = NULL, \
+ .dst = NULL, \
+ .dst_size = 0, \
+ .fname = NULL, \
+ .result_size = NULL, \
+ .is_nullable = false, \
+ .is_null = NULL \
+ }
/**
@@ -742,7 +775,7 @@ GNUNET_PQ_result_spec_fixed_size (const char *name,
* @return array entry for the result specification to use
*/
#define GNUNET_PQ_result_spec_auto_from_type(name, dst) \
- GNUNET_PQ_result_spec_fixed_size (name, (dst), sizeof(*(dst)))
+ GNUNET_PQ_result_spec_fixed_size (name, (dst), sizeof(*(dst)))
/**
@@ -1050,12 +1083,12 @@ GNUNET_PQ_result_spec_array_fixed_size (
* @return array entry for the result specification to use
*/
#define GNUNET_PQ_result_spec_auto_array_from_type(db, name, num, dst) \
- GNUNET_PQ_result_spec_array_fixed_size ( \
- (db), \
- (name), \
- sizeof(*(dst)), \
- (num), \
- (void *) &(dst))
+ GNUNET_PQ_result_spec_array_fixed_size ( \
+ (db), \
+ (name), \
+ sizeof(*(dst)), \
+ (num), \
+ (void *) &(dst))
/**
@@ -1247,9 +1280,9 @@ struct GNUNET_PQ_PreparedStatement
* Terminator for prepared statement list.
*/
#define GNUNET_PQ_PREPARED_STATEMENT_END \
- { \
- NULL, NULL \
- }
+ { \
+ NULL, NULL \
+ }
/**
@@ -1319,9 +1352,9 @@ struct GNUNET_PQ_ExecuteStatement
* Terminator for executable statement list.
*/
#define GNUNET_PQ_EXECUTE_STATEMENT_END \
- { \
- NULL, GNUNET_SYSERR \
- }
+ { \
+ NULL, GNUNET_SYSERR \
+ }
/**
diff --git a/src/pq/pq_connect.c b/src/pq/pq_connect.c
@@ -430,6 +430,45 @@ GNUNET_PQ_get_oid (
}
+enum GNUNET_GenericReturnValue
+GNUNET_PQ_get_oid_by_name (
+ struct GNUNET_PQ_Context *db,
+ const char *name,
+ Oid *oid)
+{
+ char *typname;
+ enum GNUNET_DB_QueryStatus qs;
+ struct GNUNET_PQ_QueryParam params[] = {
+ GNUNET_PQ_query_param_string (name),
+ GNUNET_PQ_query_param_end
+ };
+ struct GNUNET_PQ_ResultSpec rs[] = {
+ GNUNET_PQ_result_spec_string ("typname",
+ &typname),
+ GNUNET_PQ_result_spec_uint32 ("oid",
+ oid),
+ GNUNET_PQ_result_spec_end
+ };
+
+ GNUNET_assert (NULL != db);
+
+ /* Initialize to Oid(0) (= unknown) */
+ *oid = 0;
+
+ qs = GNUNET_PQ_eval_prepared_singleton_select (db,
+ "gnunet_pq_get_oid_by_name",
+ params,
+ rs);
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+ return GNUNET_SYSERR;
+
+ if (0 != strcasecmp (typname, name))
+ return GNUNET_SYSERR;
+
+ return GNUNET_OK;
+}
+
+
void
GNUNET_PQ_reconnect (struct GNUNET_PQ_Context *db)
{
@@ -530,6 +569,33 @@ GNUNET_PQ_reconnect (struct GNUNET_PQ_Context *db)
return;
}
+ /* Prepare statement for OID lookup by name */
+ {
+ PGresult *res;
+
+ res = PQprepare (db->conn,
+ "gnunet_pq_get_oid_by_name",
+ "SELECT"
+ " typname, oid"
+ " FROM pg_type"
+ " WHERE typname = $1"
+ " LIMIT 1",
+ 1,
+ NULL);
+ if (PGRES_COMMAND_OK != PQresultStatus (res))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to run SQL statement prepare OID lookups: %s/%s\n",
+ PQresultErrorMessage (res),
+ PQerrorMessage (db->conn));
+ PQclear (res);
+ PQfinish (db->conn);
+ db->conn = NULL;
+ return;
+ }
+ PQclear (res);
+ }
+
if (NULL != db->auto_suffix)
{
PGresult *res;
diff --git a/src/pq/test_pq.c b/src/pq/test_pq.c
@@ -554,6 +554,41 @@ main (int argc,
GNUNET_PQ_disconnect (db);
return ret;
}
+
+ /* ensure oid lookup works */
+ {
+ enum GNUNET_GenericReturnValue ret;
+ Oid oid;
+
+ ret = GNUNET_PQ_get_oid_by_name (db, "int8", &oid);
+
+ if (GNUNET_OK != ret)
+ {
+ fprintf (stderr,
+ "Cannot lookup oid for int8: %s\n",
+ PQerrorMessage (db->conn));
+ GNUNET_break (0);
+ GNUNET_PQ_disconnect (db);
+ return 77; /* signal test was skipped */
+ }
+
+ PQexec (db->conn, "CREATE TYPE foo AS (foo int, bar int);");
+
+ ret = GNUNET_PQ_get_oid_by_name (db, "foo", &oid);
+ if (GNUNET_OK != ret)
+ {
+ fprintf (stderr,
+ "Cannot lookup oid for foo: %s\n",
+ PQerrorMessage (db->conn));
+ GNUNET_break (0);
+ GNUNET_PQ_disconnect (db);
+ return 77; /* signal test was skipped */
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "got oid %d for type foo\n", oid);
+ }
+
GNUNET_SCHEDULER_run (&sched_tests,
NULL);
if (0 != ret)