gnunet

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

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:
Msrc/include/gnunet_pq_lib.h | 115+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Msrc/pq/pq_connect.c | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/pq/test_pq.c | 35+++++++++++++++++++++++++++++++++++
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)