From 8b3286e953a80cf069271957ec817485ebe5b14e Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 27 Feb 2017 02:08:21 +0100 Subject: [PATCH] implement sq_query_helper.c --- po/POTFILES.in | 11 +- src/include/gnunet_pq_lib.h | 14 -- src/include/gnunet_sq_lib.h | 23 ++- src/sq/Makefile.am | 2 +- src/sq/sq.c | 43 ++++- src/sq/sq_query_helper.c | 314 ++++++++++++++++++++++++++++++++++++ src/sq/sq_result_helper.c | 38 +++-- 7 files changed, 402 insertions(+), 43 deletions(-) diff --git a/po/POTFILES.in b/po/POTFILES.in index 2594104df..6c156336b 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -65,6 +65,7 @@ src/cadet/gnunet-service-cadet_tunnel.c src/consensus/consensus_api.c src/consensus/gnunet-consensus-profiler.c src/consensus/gnunet-service-consensus.c +src/consensus/plugin_block_consensus.c src/conversation/conversation_api.c src/conversation/conversation_api_call.c src/conversation/gnunet-conversation.c @@ -114,13 +115,6 @@ src/dht/gnunet-service-dht_hello.c src/dht/gnunet-service-dht_neighbours.c src/dht/gnunet-service-dht_nse.c src/dht/gnunet-service-dht_routing.c -src/dht/gnunet-service-wdht.c -src/dht/gnunet-service-wdht_clients.c -src/dht/gnunet-service-wdht_neighbours.c -src/dht/gnunet-service-xdht.c -src/dht/gnunet-service-xdht_hello.c -src/dht/gnunet-service-xdht_neighbours.c -src/dht/gnunet-service-xdht_routing.c src/dht/plugin_block_dht.c src/dns/dns_api.c src/dns/dnsparser.c @@ -349,6 +343,9 @@ src/set/set_api.c src/social/gnunet-service-social.c src/social/gnunet-social.c src/social/social_api.c +src/sq/sq.c +src/sq/sq_query_helper.c +src/sq/sq_result_helper.c src/statistics/gnunet-service-statistics.c src/statistics/gnunet-statistics.c src/statistics/statistics_api.c diff --git a/src/include/gnunet_pq_lib.h b/src/include/gnunet_pq_lib.h index e8180f286..756370b74 100644 --- a/src/include/gnunet_pq_lib.h +++ b/src/include/gnunet_pq_lib.h @@ -316,20 +316,6 @@ GNUNET_PQ_result_spec_fixed_size (const char *name, #define GNUNET_PQ_result_spec_auto_from_type(name, dst) GNUNET_PQ_result_spec_fixed_size (name, (dst), sizeof (*(dst))) -/** - * 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, - size_t *sptr); - - /** * 0-terminated string expected. * diff --git a/src/include/gnunet_sq_lib.h b/src/include/gnunet_sq_lib.h index a068650ac..1606d1129 100644 --- a/src/include/gnunet_sq_lib.h +++ b/src/include/gnunet_sq_lib.h @@ -21,7 +21,7 @@ #ifndef GNUNET_SQ_LIB_H #define GNUNET_SQ_LIB_H -#include +#include #include "gnunet_util_lib.h" @@ -186,7 +186,8 @@ GNUNET_SQ_query_param_uint64 (const uint64_t *x); * * @param cls closure * @param result where to extract data from - * @param int row to extract data from + * @param row row to extract data from + * @param column column to extract data from * @param[in,out] dst_size where to store size of result, may be NULL * @param[out] dst where to store the result * @return @@ -197,20 +198,25 @@ typedef int (*GNUNET_SQ_ResultConverter)(void *cls, sqlite3_stmt *result, int row, + unsigned int column, size_t *dst_size, void *dst); +/** + * @brief Description of a DB result cell. + */ +struct GNUNET_SQ_ResultSpec; + + /** * Function called to clean up memory allocated * by a #GNUNET_SQ_ResultConverter. * * @param cls closure - * @param rd result data to clean up */ typedef void -(*GNUNET_SQ_ResultCleanup)(void *cls, - void *rd); +(*GNUNET_SQ_ResultCleanup)(void *cls); /** @@ -252,6 +258,11 @@ struct GNUNET_SQ_ResultSpec */ size_t *result_size; + /** + * Number of parameters (columns) eaten by this operation. + */ + unsigned int num_params; + }; @@ -407,7 +418,7 @@ GNUNET_SQ_bind (sqlite3_stmt *stmt, * @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_OK if all results could be extracted * #GNUNET_SYSERR if a result was invalid (non-existing field) */ int diff --git a/src/sq/Makefile.am b/src/sq/Makefile.am index 7197e7ab4..c5f80bcf6 100644 --- a/src/sq/Makefile.am +++ b/src/sq/Makefile.am @@ -17,7 +17,7 @@ libgnunetsq_la_SOURCES = \ sq.c \ sq_query_helper.c \ sq_result_helper.c -libgnunetsq_la_LIBADD = -lsq \ +libgnunetsq_la_LIBADD = -lsqlite3 \ $(top_builddir)/src/util/libgnunetutil.la libgnunetsq_la_LDFLAGS = \ $(POSTGRESQL_LDFLAGS) \ diff --git a/src/sq/sq.c b/src/sq/sq.c index 524014b0f..74ab7beb5 100644 --- a/src/sq/sq.c +++ b/src/sq/sq.c @@ -33,6 +33,28 @@ int GNUNET_SQ_bind (sqlite3_stmt *stmt, const struct GNUNET_SQ_QueryParam *params) { + unsigned int j; + + j = 1; + for (unsigned int i=0;NULL != params[i].conv; i++) + { + if (GNUNET_OK != + params[i].conv (params[i].conv_cls, + params[i].data, + params[i].size, + stmt, + j)) + { + GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, + "sq", + _("Failure to bind %u-th SQL parameter\n"), + i); + return GNUNET_SYSERR; + } + GNUNET_assert (0 != params[i].num_params); + j += params[i].num_params; + } + return GNUNET_OK; } @@ -43,7 +65,7 @@ GNUNET_SQ_bind (sqlite3_stmt *stmt, * @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_OK if all results could be extracted * #GNUNET_SYSERR if a result was invalid (non-existing field) */ int @@ -51,6 +73,22 @@ GNUNET_SQ_extract_result (sqlite3_stmt *result, struct GNUNET_SQ_ResultSpec *rs, int row) { + unsigned int j = 0; + + for (unsigned int i=0;NULL != rs[i].conv; i++) + { + if (GNUNET_OK != + rs[i].conv (rs[i].cls, + result, + row, + j, + rs[i].result_size, + rs[i].dst)) + return GNUNET_SYSERR; + GNUNET_assert (0 != rs[i].num_params); + j += rs[i].num_params; + } + return GNUNET_OK; } @@ -63,6 +101,9 @@ GNUNET_SQ_extract_result (sqlite3_stmt *result, void GNUNET_SQ_cleanup_result (struct GNUNET_SQ_ResultSpec *rs) { + for (unsigned int i=0;NULL != rs[i].conv; i++) + if (NULL != rs[i].cleaner) + rs[i].cleaner (rs[i].cls); } /* end of sq.c */ diff --git a/src/sq/sq_query_helper.c b/src/sq/sq_query_helper.c index 613a0c746..5529c5e6c 100644 --- a/src/sq/sq_query_helper.c +++ b/src/sq/sq_query_helper.c @@ -18,9 +18,39 @@ * @brief helper functions for queries * @author Christian Grothoff */ +#include "platform.h" #include "gnunet_sq_lib.h" +/** + * 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 stmt sqlite statement to bind parameters for + * @param off offset of the argument to bind in @a stmt, numbered from 1, + * so immediately suitable for passing to `sqlite3_bind`-functions. + * @return #GNUNET_SYSERR on error, #GNUNET_OK on success + */ +static int +bind_fixed_blob (void *cls, + const void *data, + size_t data_len, + sqlite3_stmt *stmt, + unsigned int off) +{ + if (SQLITE_OK != + sqlite3_bind_blob64 (stmt, + (int) off, + data, + (sqlite3_uint64) data_len, + SQLITE_TRANSIENT)) + return GNUNET_SYSERR; + return GNUNET_OK; +} + + /** * Generate query parameter for a buffer @a ptr of * @a ptr_size bytes. @@ -32,6 +62,42 @@ struct GNUNET_SQ_QueryParam GNUNET_SQ_query_param_fixed_size (const void *ptr, size_t ptr_size) { + struct GNUNET_SQ_QueryParam qp = { + .conv = &bind_fixed_blob, + .data = ptr, + .size = ptr_size, + .num_params = 1 + }; + return qp; +} + + +/** + * 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 stmt sqlite statement to bind parameters for + * @param off offset of the argument to bind in @a stmt, numbered from 1, + * so immediately suitable for passing to `sqlite3_bind`-functions. + * @return #GNUNET_SYSERR on error, #GNUNET_OK on success + */ +static int +bind_string (void *cls, + const void *data, + size_t data_len, + sqlite3_stmt *stmt, + unsigned int off) +{ + if (SQLITE_OK != + sqlite3_bind_text (stmt, + (int) off, + (const char *) data, + -1, + SQLITE_TRANSIENT)) + return GNUNET_SYSERR; + return GNUNET_OK; } @@ -43,6 +109,52 @@ GNUNET_SQ_query_param_fixed_size (const void *ptr, struct GNUNET_SQ_QueryParam GNUNET_SQ_query_param_string (const char *ptr) { + struct GNUNET_SQ_QueryParam qp = { + .conv = &bind_string, + .data = ptr, + .num_params = 1 + }; + return qp; +} + + +/** + * 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 stmt sqlite statement to bind parameters for + * @param off offset of the argument to bind in @a stmt, numbered from 1, + * so immediately suitable for passing to `sqlite3_bind`-functions. + * @return #GNUNET_SYSERR on error, #GNUNET_OK on success + */ +static int +bind_rsa_pub (void *cls, + const void *data, + size_t data_len, + sqlite3_stmt *stmt, + unsigned int off) +{ + const struct GNUNET_CRYPTO_RsaPublicKey *rsa = data; + char *buf; + size_t buf_size; + + GNUNET_break (NULL == cls); + buf_size = GNUNET_CRYPTO_rsa_public_key_encode (rsa, + &buf); + if (SQLITE_OK != + sqlite3_bind_blob64 (stmt, + (int) off, + buf, + (sqlite3_uint64) buf_size, + SQLITE_TRANSIENT)) + { + GNUNET_free (buf); + return GNUNET_SYSERR; + } + GNUNET_free (buf); + return GNUNET_OK; } @@ -55,6 +167,52 @@ GNUNET_SQ_query_param_string (const char *ptr) struct GNUNET_SQ_QueryParam GNUNET_SQ_query_param_rsa_public_key (const struct GNUNET_CRYPTO_RsaPublicKey *x) { + struct GNUNET_SQ_QueryParam qp = { + .conv = &bind_rsa_pub, + .data = x, + .num_params = 1 + }; + return qp; +} + + +/** + * 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 stmt sqlite statement to bind parameters for + * @param off offset of the argument to bind in @a stmt, numbered from 1, + * so immediately suitable for passing to `sqlite3_bind`-functions. + * @return #GNUNET_SYSERR on error, #GNUNET_OK on success + */ +static int +bind_rsa_sig (void *cls, + const void *data, + size_t data_len, + sqlite3_stmt *stmt, + unsigned int off) +{ + const struct GNUNET_CRYPTO_RsaSignature *sig = data; + char *buf; + size_t buf_size; + + GNUNET_break (NULL == cls); + buf_size = GNUNET_CRYPTO_rsa_signature_encode (sig, + &buf); + if (SQLITE_OK != + sqlite3_bind_blob64 (stmt, + (int) off, + buf, + (sqlite3_uint64) buf_size, + SQLITE_TRANSIENT)) + { + GNUNET_free (buf); + return GNUNET_SYSERR; + } + GNUNET_free (buf); + return GNUNET_OK; } @@ -67,6 +225,12 @@ GNUNET_SQ_query_param_rsa_public_key (const struct GNUNET_CRYPTO_RsaPublicKey *x struct GNUNET_SQ_QueryParam GNUNET_SQ_query_param_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *x) { + struct GNUNET_SQ_QueryParam qp = { + .conv = &bind_rsa_sig, + .data = x, + .num_params = 1 + }; + return qp; } @@ -79,6 +243,39 @@ GNUNET_SQ_query_param_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *x) struct GNUNET_SQ_QueryParam GNUNET_SQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x) { + return GNUNET_SQ_query_param_uint64 (&x->abs_value_us); +} + + +/** + * 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 stmt sqlite statement to bind parameters for + * @param off offset of the argument to bind in @a stmt, numbered from 1, + * so immediately suitable for passing to `sqlite3_bind`-functions. + * @return #GNUNET_SYSERR on error, #GNUNET_OK on success + */ +static int +bind_nbotime (void *cls, + const void *data, + size_t data_len, + sqlite3_stmt *stmt, + unsigned int off) +{ + const struct GNUNET_TIME_AbsoluteNBO *u = data; + struct GNUNET_TIME_Absolute abs; + + abs = GNUNET_TIME_absolute_ntoh (*u); + GNUNET_assert (sizeof (uint64_t) == data_len); + if (SQLITE_OK != + sqlite3_bind_int64 (stmt, + (int) off, + (sqlite3_int64) abs.abs_value_us)) + return GNUNET_SYSERR; + return GNUNET_OK; } @@ -91,6 +288,43 @@ GNUNET_SQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x) struct GNUNET_SQ_QueryParam GNUNET_SQ_query_param_absolute_time_nbo (const struct GNUNET_TIME_AbsoluteNBO *x) { + struct GNUNET_SQ_QueryParam qp = { + .conv = &bind_nbotime, + .data = x, + .size = sizeof (struct GNUNET_TIME_AbsoluteNBO), + .num_params = 1 + }; + return qp; +} + + +/** + * 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 stmt sqlite statement to bind parameters for + * @param off offset of the argument to bind in @a stmt, numbered from 1, + * so immediately suitable for passing to `sqlite3_bind`-functions. + * @return #GNUNET_SYSERR on error, #GNUNET_OK on success + */ +static int +bind_u16 (void *cls, + const void *data, + size_t data_len, + sqlite3_stmt *stmt, + unsigned int off) +{ + const uint16_t *u = data; + + GNUNET_assert (sizeof (uint16_t) == data_len); + if (SQLITE_OK != + sqlite3_bind_int (stmt, + (int) off, + (int) *u)) + return GNUNET_SYSERR; + return GNUNET_OK; } @@ -102,9 +336,45 @@ GNUNET_SQ_query_param_absolute_time_nbo (const struct GNUNET_TIME_AbsoluteNBO *x struct GNUNET_SQ_QueryParam GNUNET_SQ_query_param_uint16 (const uint16_t *x) { + struct GNUNET_SQ_QueryParam qp = { + .conv = &bind_u16, + .data = x, + .size = sizeof (uint16_t), + .num_params = 1 + }; + return qp; } +/** + * 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 stmt sqlite statement to bind parameters for + * @param off offset of the argument to bind in @a stmt, numbered from 1, + * so immediately suitable for passing to `sqlite3_bind`-functions. + * @return #GNUNET_SYSERR on error, #GNUNET_OK on success + */ +static int +bind_u32 (void *cls, + const void *data, + size_t data_len, + sqlite3_stmt *stmt, + unsigned int off) +{ + const uint32_t *u = data; + + GNUNET_assert (sizeof (uint32_t) == data_len); + if (SQLITE_OK != + sqlite3_bind_int64 (stmt, + (int) off, + (sqlite3_int64) *u)) + return GNUNET_SYSERR; + return GNUNET_OK; +} + /** * Generate query parameter for an uint32_t in host byte order. * @@ -113,6 +383,43 @@ GNUNET_SQ_query_param_uint16 (const uint16_t *x) struct GNUNET_SQ_QueryParam GNUNET_SQ_query_param_uint32 (const uint32_t *x) { + struct GNUNET_SQ_QueryParam qp = { + .conv = &bind_u32, + .data = x, + .size = sizeof (uint32_t), + .num_params = 1 + }; + return qp; +} + + +/** + * 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 stmt sqlite statement to bind parameters for + * @param off offset of the argument to bind in @a stmt, numbered from 1, + * so immediately suitable for passing to `sqlite3_bind`-functions. + * @return #GNUNET_SYSERR on error, #GNUNET_OK on success + */ +static int +bind_u64 (void *cls, + const void *data, + size_t data_len, + sqlite3_stmt *stmt, + unsigned int off) +{ + const uint64_t *u = data; + + GNUNET_assert (sizeof (uint64_t) == data_len); + if (SQLITE_OK != + sqlite3_bind_int64 (stmt, + (int) off, + (sqlite3_int64) *u)) + return GNUNET_SYSERR; + return GNUNET_OK; } @@ -124,6 +431,13 @@ GNUNET_SQ_query_param_uint32 (const uint32_t *x) struct GNUNET_SQ_QueryParam GNUNET_SQ_query_param_uint64 (const uint64_t *x) { + struct GNUNET_SQ_QueryParam qp = { + .conv = &bind_u64, + .data = x, + .size = sizeof (uint64_t), + .num_params = 1 + }; + return qp; } /* end of sq_query_helper.c */ diff --git a/src/sq/sq_result_helper.c b/src/sq/sq_result_helper.c index 361fea7bf..36ce53317 100644 --- a/src/sq/sq_result_helper.c +++ b/src/sq/sq_result_helper.c @@ -23,6 +23,30 @@ #include "gnunet_sq_lib.h" +/** + * Extract fixed-sized binary data from a Postgres database @a result at row @a row. + * + * @param cls closure + * @param result where to extract data from + * @param row row to extract data from + * @param column column to extract data from + * @param[in,out] dst_size where to store size of result, may be NULL + * @param[out] dst where to store the result + * @return + * #GNUNET_YES if all results could be extracted + * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) + */ +static int +extract_fixed_blob (void *cls, + sqlite3_stmt *result, + int row, + unsigned int column, + size_t *dst_size, + void *dst) +{ +} + + /** * Variable-size result expected. * @@ -51,20 +75,6 @@ GNUNET_SQ_result_spec_fixed_size (void *dst, } -/** - * Variable-size result expected. - * - * @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_SQ_ResultSpec -GNUNET_SQ_result_spec_variable_size (void **dst, - size_t *sptr) -{ -} - - /** * 0-terminated string expected. * -- 2.25.1