gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-exchange] 122/152: created taler_sq_lib


From: gnunet
Subject: [taler-exchange] 122/152: created taler_sq_lib
Date: Sun, 05 Jul 2020 20:47:58 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository exchange.

commit ef0e79927cbd64832b7351074cf71853212a331b
Author: Jonathan Buchanan <jonathan.russ.buchanan@gmail.com>
AuthorDate: Tue Jun 2 11:57:39 2020 -0400

    created taler_sq_lib
---
 .gitignore                 |   1 +
 configure.ac               |  41 +++++++++++
 src/Makefile.am            |   4 +
 src/include/taler_sq_lib.h |  52 +++++++++++++
 src/sq/Makefile.am         |  40 ++++++++++
 src/sq/sq_query_helper.c   |  77 +++++++++++++++++++
 src/sq/sq_result_helper.c  |  92 +++++++++++++++++++++++
 src/sq/test_sq.c           | 180 +++++++++++++++++++++++++++++++++++++++++++++
 8 files changed, 487 insertions(+)

diff --git a/.gitignore b/.gitignore
index e763b19e..9ed74175 100644
--- a/.gitignore
+++ b/.gitignore
@@ -81,6 +81,7 @@ src/wire-plugins/test_ebics_wireformat
 src/wire-plugins/test_wire_plugin
 src/wire-plugins/test_wire_plugin_transactions_taler_bank
 src/pq/test_pq
+src/sq/test_sq
 src/util/test_amount
 src/util/test_crypto
 src/util/test_json
diff --git a/configure.ac b/configure.ac
index 401f84c2..a51b3247 100644
--- a/configure.ac
+++ b/configure.ac
@@ -261,6 +261,16 @@ AS_IF([test $libgnunetpq != 1],
 *** ]])])
 
 
+# Check for GNUnet's libgnunetsq
+libgnunetsq=0
+AC_MSG_CHECKING([for libgnunetsq])
+AC_CHECK_HEADERS([gnunet/gnunet_sq_lib.h],
+ [AC_CHECK_LIB([gnunetsq], [GNUNET_SQ_result_spec_string], libgnunetsq=1)],
+  [], [#ifdef HAVE_GNUNET_PLATFORM_H
+        #include <gnunet/platform.h>
+       #endif])
+
+
 # check for libmicrohttpd
 microhttpd=0
 AC_MSG_CHECKING([for microhttpd])
@@ -326,6 +336,35 @@ CFLAGS=$CFLAGS_SAVE
 LDFLAGS=$LDFLAGS_SAVE
 LIBS=$LIBS_SAVE
 
+# test for sqlite
+sqlite=false
+AC_MSG_CHECKING(for SQLite)
+AC_ARG_WITH(sqlite,
+  [  --with-sqlite=PFX       base of SQLite installation],
+  [AC_MSG_RESULT("$with_sqlite")
+   AS_CASE([$with_sqlite],
+     [no],[],
+     [yes],[
+      AC_CHECK_HEADERS(sqlite3.h,
+      sqlite=true)],
+     [
+    LDFLAGS="-L$with_sqlite/lib $LDFLAGS"
+    CPPFLAGS="-I$with_sqlite/include $CPPFLAGS"
+    AC_CHECK_HEADERS(sqlite3.h,
+     EXT_LIB_PATH="-L$with_sqlite/lib $EXT_LIB_PATH"
+     SQLITE_LDFLAGS="-L$with_sqlite/lib"
+     SQLITE_CPPFLAGS="-I$with_sqlite/include"
+     sqlite=true)
+    LDFLAGS=$SAVE_LDFLAGS
+    CPPFLAGS=$SAVE_CPPFLAGS
+    ])
+  ],
+  [AC_MSG_RESULT([--with-sqlite not specified])
+    AC_CHECK_HEADERS(sqlite3.h, sqlite=true)])
+AM_CONDITIONAL(HAVE_SQLITE, [test x$sqlite = xtrue] && [test $libgnunetsq = 1])
+AC_SUBST(SQLITE_CPPFLAGS)
+AC_SUBST(SQLITE_LDFLAGS)
+
 # check for libtalertwistertesting
 talertwister=0
 AC_MSG_CHECKING([for talertwister])
@@ -459,6 +498,7 @@ AM_CONDITIONAL([ENABLE_DOC], [test "x$enable_doc" = "xyes"])
 AM_CONDITIONAL([HAVE_EXPENSIVE_TESTS], [false])
 AM_CONDITIONAL([MHD_HAVE_EPOLL], [false])
 AM_CONDITIONAL([HAVE_POSTGRESQL], [false])
+AM_CONDITIONAL([HAVE_SQLITE], [false])
 AM_CONDITIONAL([HAVE_LIBCURL], [false])
 AM_CONDITIONAL([HAVE_LIBGNURL], [false])
 AM_CONDITIONAL([HAVE_DEVELOPER], [false])
@@ -488,6 +528,7 @@ AC_CONFIG_FILES([Makefile
                  src/json/Makefile
                  src/mhd/Makefile
                  src/pq/Makefile
+                 src/sq/Makefile
                  src/util/Makefile
                  ])
 AC_OUTPUT
diff --git a/src/Makefile.am b/src/Makefile.am
index 4b07a116..4d4e533e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -3,6 +3,9 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/include
 if HAVE_POSTGRESQL
   PQ_DIR = pq
 endif
+if HAVE_SQLITE
+  SQ_DIR = sq
+endif
 
 pkgcfgdir = $(prefix)/share/taler/config.d/
 pkgcfg_DATA = \
@@ -17,6 +20,7 @@ SUBDIRS = \
   json \
   curl \
   $(PQ_DIR) \
+  $(SQ_DIR) \
   mhd \
   bank-lib \
   exchangedb \
diff --git a/src/include/taler_sq_lib.h b/src/include/taler_sq_lib.h
new file mode 100644
index 00000000..f6a35225
--- /dev/null
+++ b/src/include/taler_sq_lib.h
@@ -0,0 +1,52 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2020 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU General Public License as published by the Free Software
+  Foundation; either version 3, or (at your option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along with
+  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file include/taler_sq_lib.h
+ * @brief helper functions for DB interactions with SQLite
+ * @author Jonathan Buchanan
+ */
+#ifndef TALER_SQ_LIB_H_
+#define TALER_SQ_LIB_H_
+
+#include <sqlite3.h>
+#include <jansson.h>
+#include <gnunet/gnunet_sq_lib.h>
+#include "taler_util.h"
+
+/**
+ * Generate query parameter for a currency, consisting of the three
+ * components "value", "fraction" in this order. The
+ * types must be a 64-bit integer and a 64-bit integer.
+ *
+ * @param x pointer to the query parameter to pass
+ */
+struct GNUNET_SQ_QueryParam
+TALER_SQ_query_param_amount_nbo (const struct TALER_AmountNBO *x);
+
+/**
+ * Currency amount expected.
+ *
+ * @param currency currency to use for @a amount
+ * @param[out] amount where to store the result
+ * @return array entry for the result specification to use
+ */
+struct GNUNET_SQ_ResultSpec
+TALER_SQ_result_spec_amount_nbo (const char *currency,
+                                 struct TALER_AmountNBO *amount);
+
+#endif  /* TALER_SQ_LIB_H_ */
+
+/* end of include/taler_sq_lib.h */
diff --git a/src/sq/Makefile.am b/src/sq/Makefile.am
new file mode 100644
index 00000000..ee4c5eba
--- /dev/null
+++ b/src/sq/Makefile.am
@@ -0,0 +1,40 @@
+# This Makefile.am is in the public domain
+AM_CPPFLAGS = -I$(top_srcdir)/src/include $(LIBGCRYPT_CFLAGS) 
$(SQLITE_CPPFLAGS)
+
+if USE_COVERAGE
+  AM_CFLAGS = --coverage -O0
+  XLIB = -lgcov
+endif
+
+lib_LTLIBRARIES = \
+  libtalersq.la
+
+libtalersq_la_SOURCES = \
+  sq_query_helper.c \
+  sq_result_helper.c
+
+libtalersq_la_LIBADD = \
+  $(top_builddir)/src/util/libtalerutil.la  \
+  -lgnunetutil -ljansson \
+  -lsqlite3 $(XLIB)
+
+libtalersq_la_LDFLAGS = \
+  $(SQLITE_LDFLAGS) \
+  -version-info 0:0:0 \
+  -export-dynamic -no-undefined
+
+TESTS = \
+ test_sq
+
+check_PROGRAMS= \
+ test_sq
+
+test_sq_SOURCES = \
+  test_sq.c
+test_sq_LDADD = \
+  libtalersq.la \
+  $(top_builddir)/src/util/libtalerutil.la  \
+  -lgnunetsq \
+  -lgnunetutil \
+  -ljansson \
+  -lsqlite3 $(XLIB)
diff --git a/src/sq/sq_query_helper.c b/src/sq/sq_query_helper.c
new file mode 100644
index 00000000..8116622a
--- /dev/null
+++ b/src/sq/sq_query_helper.c
@@ -0,0 +1,77 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2020 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU General Public License as published by the Free Software
+  Foundation; either version 3, or (at your option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along with
+  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file sq/sq_query_helper.c
+ * @brief helper functions for Taler-specific SQLite3 interactions
+ * @author Jonathan Buchanan
+ */
+#include "platform.h"
+#include <sqlite3.h>
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_sq_lib.h>
+#include "taler_sq_lib.h"
+
+
+/**
+ * Function called to convert input argument into SQL parameters.
+ *
+ * @param cls closure
+ * @param data pointer to input argument, here a `struct TALER_AmountNBO`
+ * @param data_len number of bytes in @a data (if applicable)
+ * @param stmt sqlite statement to 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
+qconv_amount_nbo (void *cls,
+                  const void *data,
+                  size_t data_len,
+                  sqlite3_stmt *stmt,
+                  unsigned int off)
+{
+  const struct TALER_AmountNBO *amount = data;
+
+  GNUNET_assert (sizeof (struct TALER_AmountNBO) == data_len);
+  if (SQLITE_OK != sqlite3_bind_int64 (stmt,
+                                       (int) off,
+                                       (sqlite3_int64) amount->value))
+    return GNUNET_SYSERR;
+  if (SQLITE_OK != sqlite3_bind_int64 (stmt,
+                                       (int) off + 1,
+                                       (sqlite3_int64) amount->fraction))
+    return GNUNET_SYSERR;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Generate query parameter for a currency, consisting of the three
+ * components "value", "fraction" in this order. The
+ * types must be a 64-bit integer and a 64-bit integer.
+ *
+ * @param x pointer to the query parameter to pass
+ */
+struct GNUNET_SQ_QueryParam
+TALER_SQ_query_param_amount_nbo (const struct TALER_AmountNBO *x)
+{
+  struct GNUNET_SQ_QueryParam res =
+  { &qconv_amount_nbo, NULL, x, sizeof (*x), 2 };
+  return res;
+}
+
+
+/* end of sq/sq_query_helper.c */
diff --git a/src/sq/sq_result_helper.c b/src/sq/sq_result_helper.c
new file mode 100644
index 00000000..ef36d3e9
--- /dev/null
+++ b/src/sq/sq_result_helper.c
@@ -0,0 +1,92 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2020 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU General Public License as published by the Free Software
+  Foundation; either version 3, or (at your option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along with
+  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file sq/sq_result_helper.c
+ * @brief functions to initialize parameter arrays
+ * @author Jonathan Buchanan
+ */
+#include "platform.h"
+#include <sqlite3.h>
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_sq_lib.h>
+#include "taler_sq_lib.h"
+#include "taler_amount_lib.h"
+
+
+/**
+ * Extract amount data from a SQLite database
+ *
+ * @param cls closure, a `const char *` giving the currency
+ * @param result where 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_amount_nbo (void *cls,
+                    sqlite3_stmt *result,
+                    unsigned int column,
+                    size_t *dst_size,
+                    void *dst)
+{
+  struct TALER_AmountNBO *amount = dst;
+  const char *currency = cls;
+  if ((sizeof (struct TALER_AmountNBO) != *dst_size) ||
+      (SQLITE_INTEGER != sqlite3_column_type (result,
+                                              (int) column)) ||
+      (SQLITE_INTEGER != sqlite3_column_type (result,
+                                              (int) column + 1)))
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_strlcpy (amount->currency, currency, TALER_CURRENCY_LEN);
+  amount->value = (uint64_t) sqlite3_column_int64 (result,
+                                                   (int) column);
+  uint64_t frac = (uint64_t) sqlite3_column_int64 (result,
+                                                   column + 1);
+  amount->fraction = (uint32_t) frac;
+  return GNUNET_YES;
+}
+
+
+/**
+ * Currency amount expected.
+ *
+ * @param currency the currency to use for @a amount
+ * @param[out] amount where to store the result
+ * @return array entry for the result specification to use
+ */
+struct GNUNET_SQ_ResultSpec
+TALER_SQ_result_spec_amount_nbo (const char *currency,
+                                 struct TALER_AmountNBO *amount)
+{
+  struct GNUNET_SQ_ResultSpec res = {
+    .conv = &extract_amount_nbo,
+    .cls = (void *) currency,
+    .dst = (void *) amount,
+    .dst_size = sizeof (struct TALER_AmountNBO),
+    .num_params = 2
+  };
+
+  return res;
+}
+
+
+/* end of sq/sq_result_helper.c */
diff --git a/src/sq/test_sq.c b/src/sq/test_sq.c
new file mode 100644
index 00000000..85f837e4
--- /dev/null
+++ b/src/sq/test_sq.c
@@ -0,0 +1,180 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2020 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU General Public License as published by the Free Software
+  Foundation; either version 3, or (at your option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along with
+  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file sq/test_sq.c
+ * @brief Tests for SQLite3 convenience API
+ * @author Jonathan Buchanan
+ */
+#include "platform.h"
+#include "taler_sq_lib.h"
+
+
+/**
+ * Run actual test queries.
+ *
+ * @return 0 on success
+ */
+static int
+run_queries (sqlite3 *db)
+{
+  struct TALER_Amount hamount;
+  struct TALER_AmountNBO namount;
+  sqlite3_stmt *test_insert;
+  sqlite3_stmt *test_select;
+  struct GNUNET_SQ_PrepareStatement ps[] = {
+    GNUNET_SQ_make_prepare ("INSERT INTO test_sq ("
+                            " namount_val"
+                            ",namount_frac"
+                            ") VALUES "
+                            "($1, $2)",
+                            &test_insert),
+    GNUNET_SQ_make_prepare ("SELECT"
+                            " namount_val"
+                            ",namount_frac"
+                            " FROM test_sq",
+                            &test_select),
+    GNUNET_SQ_PREPARE_END
+  };
+
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_string_to_amount ("EUR:1.23",
+                                         &hamount));
+  TALER_amount_hton (&namount,
+                     &hamount);
+
+  GNUNET_assert (GNUNET_OK == GNUNET_SQ_prepare (db,
+                                                 ps));
+
+  {
+    struct GNUNET_SQ_QueryParam params_insert[] = {
+      TALER_SQ_query_param_amount_nbo (&namount),
+      GNUNET_SQ_query_param_end
+    };
+    GNUNET_SQ_reset (db,
+                     test_insert);
+    GNUNET_assert (GNUNET_OK == GNUNET_SQ_bind (test_insert,
+                                                params_insert));
+    GNUNET_assert (SQLITE_DONE == sqlite3_step (test_insert));
+    sqlite3_finalize (test_insert);
+  }
+
+  {
+    struct TALER_AmountNBO nresult_amount;
+    struct TALER_Amount result_amount;
+    struct GNUNET_SQ_QueryParam params_select[] = {
+      GNUNET_SQ_query_param_end
+    };
+    struct GNUNET_SQ_ResultSpec results_select[] = {
+      TALER_SQ_result_spec_amount_nbo ("EUR",
+                                       &nresult_amount),
+      GNUNET_SQ_result_spec_end
+    };
+
+    GNUNET_SQ_reset (db,
+                     test_select);
+    GNUNET_assert (GNUNET_OK == GNUNET_SQ_bind (test_select,
+                                                params_select));
+    GNUNET_assert (SQLITE_ROW == sqlite3_step (test_select));
+
+    GNUNET_assert (GNUNET_OK == GNUNET_SQ_extract_result (test_select,
+                                                          results_select));
+    GNUNET_SQ_cleanup_result (results_select);
+    sqlite3_finalize (test_select);
+    TALER_amount_ntoh (&result_amount, &nresult_amount);
+    if ((GNUNET_OK != TALER_amount_cmp_currency (&hamount,
+                                                 &result_amount)) ||
+        (0 != TALER_amount_cmp (&hamount,
+                                &result_amount)))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Result from database doesn't match input\n");
+      return 1;
+    }
+  }
+
+  return 0;
+}
+
+
+int
+main (int argc,
+      const char *const argv[])
+{
+  struct GNUNET_SQ_ExecuteStatement es[] = {
+    GNUNET_SQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS test_sq ("
+                            " namount_val INT8 NOT NULL"
+                            ",namount_frac INT4 NOT NULL"
+                            ")"),
+    GNUNET_SQ_EXECUTE_STATEMENT_END
+  };
+  sqlite3 *db;
+  int ret;
+
+  GNUNET_log_setup ("test-pq",
+                    "WARNING",
+                    NULL);
+
+  if (SQLITE_OK != sqlite3_open ("talercheck.db",
+                                 &db))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to open SQLite3 database\n");
+    return 77;
+  }
+
+  if (GNUNET_OK != GNUNET_SQ_exec_statements (db,
+                                              es))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to create new table\n");
+    if ((SQLITE_OK != sqlite3_close (db)) ||
+        (0 != unlink ("talercheck.db")))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Failed to close db or unlink\n");
+    }
+    return 1;
+  }
+
+  ret = run_queries (db);
+
+  if (SQLITE_OK !=
+      sqlite3_exec (db,
+                    "DROP TABLE test_sq",
+                    NULL, NULL, NULL))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to drop table\n");
+    ret = 1;
+  }
+
+  if (SQLITE_OK != sqlite3_close (db))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to close database\n");
+    ret = 1;
+  }
+  if (0 != unlink ("talercheck.db"))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to unlink test database file\n");
+    ret = 1;
+  }
+  return ret;
+}
+
+
+/* end of sq/test_sq.c */

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]