summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÖzgür Kesim <oec-taler@kesim.org>2023-05-06 15:21:41 +0200
committerÖzgür Kesim <oec-taler@kesim.org>2023-05-06 15:21:41 +0200
commit25fb12006dd655e31e345593ad5da2ef724b5c45 (patch)
treef805fa3c4cf661f27fd66172bbbaeec33c389b28
parentcd8d83a631c92086a606fad0952219333afc3272 (diff)
pq: add array-type support for PQ [WIP, 1/n]
NEWS: initial steps towards support of array-types in posgresql - added enum GNUNET_PQ_ArrayTypes - generate mapping of supported array-types and OIDs during connect()
-rw-r--r--src/include/gnunet_pq_lib.h15
-rw-r--r--src/pq/pq.h6
-rw-r--r--src/pq/pq_connect.c111
3 files changed, 131 insertions, 1 deletions
diff --git a/src/include/gnunet_pq_lib.h b/src/include/gnunet_pq_lib.h
index 4cbc2a139..3e4ce3427 100644
--- a/src/include/gnunet_pq_lib.h
+++ b/src/include/gnunet_pq_lib.h
@@ -148,6 +148,21 @@ GNUNET_PQ_query_param_bool (bool b);
/**
+ * Array types (in Postgres) that are supported in GNUnet.
+ */
+enum GNUNET_PQ_ArrayTypes
+{
+ GNUNET_PQ_ARRAY_UNKNOWN, /* Unsupported type */
+ GNUNET_PQ_ARRAY_BOOL,
+ GNUNET_PQ_ARRAY_INT2,
+ GNUNET_PQ_ARRAY_INT4,
+ GNUNET_PQ_ARRAY_INT8,
+ GNUNET_PQ_ARRAY_BYTEA,
+ GNUNET_PQ_ARRAY_VARCHAR,
+ GNUNET_PQ_ARRAY_MAX, /* Must be last */
+};
+
+/**
* Information for an array argument.
*/
struct GNUNET_PQ_ArraySpec
diff --git a/src/pq/pq.h b/src/pq/pq.h
index f9b59e058..e69f0ed96 100644
--- a/src/pq/pq.h
+++ b/src/pq/pq.h
@@ -98,9 +98,15 @@ struct GNUNET_PQ_Context
* Flags controlling the connection.
*/
enum GNUNET_PQ_Options flags;
+
+ /**
+ * Mapping between array types and Oid's, filled at reconnect
+ */
+ Oid arraytype2oid[GNUNET_PQ_ARRAY_MAX];
};
+
/**
* Internal API. Reconnect should re-register notifications
* after a disconnect.
diff --git a/src/pq/pq_connect.c b/src/pq/pq_connect.c
index 02af17c8c..f6fd3e34b 100644
--- a/src/pq/pq_connect.c
+++ b/src/pq/pq_connect.c
@@ -1,6 +1,6 @@
/*
This file is part of GNUnet
- Copyright (C) 2017, 2019, 2020, 2021 GNUnet e.V.
+ Copyright (C) 2017, 2019, 2020, 2021, 2023 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
@@ -21,6 +21,7 @@
* @file pq/pq_connect.c
* @brief functions to connect to libpq (PostGres)
* @author Christian Grothoff
+ * @author Özgür Kesim
*/
#include "platform.h"
#include "pq.h"
@@ -321,6 +322,103 @@ GNUNET_PQ_reconnect_if_down (struct GNUNET_PQ_Context *db)
}
+/**
+ * Retrieves the Oid's for the supported array types and sets db->arraytype2oid
+ * on succes.
+ *
+ * @param db Context for the database connection
+ * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
+ */
+static enum GNUNET_GenericReturnValue
+get_array_type_oids (struct GNUNET_PQ_Context *db)
+{
+ PGresult *res;
+ ExecStatusType est;
+ GNUNET_assert (NULL != db);
+
+ /* Initialize to Oid(0) (= unknown) */
+ memset (db->arraytype2oid,
+ 0,
+ sizeof(db->arraytype2oid));
+
+ res = PQexec (db->conn,
+ "SELECT"
+ " typname, oid"
+ " FROM pg_type "
+ " WHERE typname like '\\_%';");
+
+ est = PQresultStatus (res);
+ if ( (PGRES_COMMAND_OK != est) &&
+ (PGRES_TUPLES_OK != est))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to run statement to retrieve Oids for array types!\n");
+ return GNUNET_SYSERR;
+ }
+
+ if ( (2 != PQnfields (res)) ||
+ (0 != PQfnumber (res, "typname")) ||
+ (1 != PQfnumber (res, "oid"))
+ )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected table retrieved for array types\n");
+ return GNUNET_SYSERR;
+ }
+
+ {
+ int nrows = PQntuples (res);
+ int nfound = 1; /* skip GNUNET_PQ_ARRAY_UNKNOWN */
+
+ for (int r = 0; r < nrows; r++)
+ {
+ enum GNUNET_PQ_ArrayTypes atype = GNUNET_PQ_ARRAY_UNKNOWN;
+ char *typ_s = PQgetvalue (res,r,0);
+ char *oid_s = PQgetvalue (res,r,1);
+ GNUNET_assert (NULL != typ_s);
+ GNUNET_assert (NULL != oid_s);
+
+ if (! strcmp (typ_s,"_bool"))
+ atype = GNUNET_PQ_ARRAY_BOOL;
+ else if (! strcmp (typ_s,"_int2"))
+ atype = GNUNET_PQ_ARRAY_INT2;
+ else if (! strcmp (typ_s,"_int4"))
+ atype = GNUNET_PQ_ARRAY_INT4;
+ else if (! strcmp (typ_s,"_int8"))
+ atype = GNUNET_PQ_ARRAY_INT8;
+ else if (! strcmp (typ_s,"_bytea"))
+ atype = GNUNET_PQ_ARRAY_BYTEA;
+ else if (! strcmp (typ_s,"_varchar"))
+ atype = GNUNET_PQ_ARRAY_VARCHAR;
+ else
+ continue;
+
+ GNUNET_assert (GNUNET_PQ_ARRAY_MAX > atype);
+
+ if ((GNUNET_PQ_ARRAY_UNKNOWN != atype) &&
+ (1 == sscanf (oid_s, "%u", &db->arraytype2oid[atype])))
+ {
+ nfound++;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "OID[%s]: %d\n",
+ typ_s, db->arraytype2oid[atype]);
+ }
+ }
+
+ if (GNUNET_PQ_ARRAY_MAX != nfound)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Couldn't find all array types, only found %d of %d!\n",
+ nfound - 1,
+ GNUNET_PQ_ARRAY_MAX - 1);
+ return GNUNET_SYSERR;
+ }
+ }
+
+ return GNUNET_OK;
+}
+
+
void
GNUNET_PQ_reconnect (struct GNUNET_PQ_Context *db)
{
@@ -411,6 +509,16 @@ GNUNET_PQ_reconnect (struct GNUNET_PQ_Context *db)
}
}
+ /* Retrieve the OIDs for the supported Array types */
+ if (GNUNET_SYSERR == get_array_type_oids (db))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to retrieve OID information for array types!\n");
+ PQfinish (db->conn);
+ db->conn = NULL;
+ return;
+ }
+
if (NULL != db->auto_suffix)
{
PGresult *res;
@@ -450,6 +558,7 @@ GNUNET_PQ_reconnect (struct GNUNET_PQ_Context *db)
return;
}
}
+
if ( (NULL != db->es) &&
(GNUNET_OK !=
GNUNET_PQ_exec_statements (db,