diff options
Diffstat (limited to 'src/lib/sq')
-rw-r--r-- | src/lib/sq/.gitignore | 1 | ||||
-rw-r--r-- | src/lib/sq/Makefile.am | 38 | ||||
-rw-r--r-- | src/lib/sq/meson.build | 30 | ||||
-rw-r--r-- | src/lib/sq/sq.c | 131 | ||||
-rw-r--r-- | src/lib/sq/sq_exec.c | 113 | ||||
-rw-r--r-- | src/lib/sq/sq_prepare.c | 77 | ||||
-rw-r--r-- | src/lib/sq/sq_query_helper.c | 510 | ||||
-rw-r--r-- | src/lib/sq/sq_result_helper.c | 785 | ||||
-rw-r--r-- | src/lib/sq/test_sq.c | 291 |
9 files changed, 1976 insertions, 0 deletions
diff --git a/src/lib/sq/.gitignore b/src/lib/sq/.gitignore new file mode 100644 index 000000000..951587047 --- /dev/null +++ b/src/lib/sq/.gitignore | |||
@@ -0,0 +1 @@ | |||
test_sq | |||
diff --git a/src/lib/sq/Makefile.am b/src/lib/sq/Makefile.am new file mode 100644 index 000000000..a77a380af --- /dev/null +++ b/src/lib/sq/Makefile.am | |||
@@ -0,0 +1,38 @@ | |||
1 | # This Makefile.am is in the public domain | ||
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | ||
3 | |||
4 | if USE_COVERAGE | ||
5 | AM_CFLAGS = --coverage | ||
6 | endif | ||
7 | |||
8 | if HAVE_SQLITE | ||
9 | lib_LTLIBRARIES = libgnunetsq.la | ||
10 | endif | ||
11 | |||
12 | libgnunetsq_la_SOURCES = \ | ||
13 | sq.c \ | ||
14 | sq_exec.c \ | ||
15 | sq_prepare.c \ | ||
16 | sq_query_helper.c \ | ||
17 | sq_result_helper.c | ||
18 | libgnunetsq_la_LIBADD = -lsqlite3 \ | ||
19 | $(top_builddir)/src/lib/util/libgnunetutil.la | ||
20 | libgnunetsq_la_LDFLAGS = \ | ||
21 | $(GN_LIBINTL) \ | ||
22 | $(GN_LIB_LDFLAGS) \ | ||
23 | -version-info 0:0:0 | ||
24 | |||
25 | if ENABLE_TEST_RUN | ||
26 | TESTS = \ | ||
27 | test_sq | ||
28 | endif | ||
29 | |||
30 | check_PROGRAMS= \ | ||
31 | test_sq | ||
32 | |||
33 | test_sq_SOURCES = \ | ||
34 | test_sq.c | ||
35 | test_sq_LDADD = \ | ||
36 | libgnunetsq.la \ | ||
37 | $(top_builddir)/src/lib/util/libgnunetutil.la \ | ||
38 | -lsqlite3 $(XLIB) | ||
diff --git a/src/lib/sq/meson.build b/src/lib/sq/meson.build new file mode 100644 index 000000000..69d372cac --- /dev/null +++ b/src/lib/sq/meson.build | |||
@@ -0,0 +1,30 @@ | |||
1 | libgnunetsq_src = ['sq.c', | ||
2 | 'sq_exec.c', | ||
3 | 'sq_prepare.c', | ||
4 | 'sq_query_helper.c', | ||
5 | 'sq_result_helper.c'] | ||
6 | |||
7 | libgnunetsq = library('gnunetsq', | ||
8 | libgnunetsq_src, | ||
9 | soversion: '0', | ||
10 | version: '0.0.0', | ||
11 | dependencies: [libgnunetutil_dep, sqlite_dep], | ||
12 | include_directories: [incdir, configuration_inc], | ||
13 | install: true, | ||
14 | install_dir: get_option('libdir')) | ||
15 | pkg.generate(libgnunetsq, url: 'https://www.gnunet.org', | ||
16 | description : 'Provides API for accessing the SQ service') | ||
17 | libgnunetsq_dep = declare_dependency(link_with : libgnunetsq) | ||
18 | testsq = executable ('test_sq', | ||
19 | ['test_sq.c'], | ||
20 | dependencies: [libgnunetutil_dep, | ||
21 | sqlite_dep, | ||
22 | libgnunetsq_dep], | ||
23 | include_directories: [incdir, configuration_inc], | ||
24 | build_by_default: false, | ||
25 | install: false) | ||
26 | test('test_sq', testsq, | ||
27 | workdir: meson.current_build_dir(), | ||
28 | suite: ['sq']) | ||
29 | |||
30 | |||
diff --git a/src/lib/sq/sq.c b/src/lib/sq/sq.c new file mode 100644 index 000000000..96d1d333d --- /dev/null +++ b/src/lib/sq/sq.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file sq/sq.c | ||
22 | * @brief helper functions for Sqlite3 DB interactions | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_sq_lib.h" | ||
27 | |||
28 | |||
29 | enum GNUNET_GenericReturnValue | ||
30 | GNUNET_SQ_bind (sqlite3_stmt *stmt, | ||
31 | const struct GNUNET_SQ_QueryParam *params) | ||
32 | { | ||
33 | unsigned int j; | ||
34 | |||
35 | j = 1; | ||
36 | for (unsigned int i = 0; NULL != params[i].conv; i++) | ||
37 | { | ||
38 | if (GNUNET_OK != | ||
39 | params[i].conv (params[i].conv_cls, | ||
40 | params[i].data, | ||
41 | params[i].size, | ||
42 | stmt, | ||
43 | j)) | ||
44 | { | ||
45 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, | ||
46 | "sq", | ||
47 | _ ("Failure to bind %u-th SQL parameter\n"), | ||
48 | i); | ||
49 | if (SQLITE_OK != | ||
50 | sqlite3_reset (stmt)) | ||
51 | { | ||
52 | GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, | ||
53 | "sq", | ||
54 | _ ("Failure in sqlite3_reset (!)\n")); | ||
55 | return GNUNET_SYSERR; | ||
56 | } | ||
57 | } | ||
58 | GNUNET_assert (0 != params[i].num_params); | ||
59 | j += params[i].num_params; | ||
60 | } | ||
61 | return GNUNET_OK; | ||
62 | } | ||
63 | |||
64 | |||
65 | /** | ||
66 | * Extract results from a query result according to the given specification. | ||
67 | * | ||
68 | * @param result result to process | ||
69 | * @param[in,out] rs result specification to extract for | ||
70 | * @return | ||
71 | * #GNUNET_OK if all results could be extracted | ||
72 | * #GNUNET_SYSERR if a result was invalid (non-existing field) | ||
73 | */ | ||
74 | enum GNUNET_GenericReturnValue | ||
75 | GNUNET_SQ_extract_result (sqlite3_stmt *result, | ||
76 | struct GNUNET_SQ_ResultSpec *rs) | ||
77 | { | ||
78 | unsigned int j = 0; | ||
79 | |||
80 | for (unsigned int i = 0; NULL != rs[i].conv; i++) | ||
81 | { | ||
82 | if (NULL == rs[i].result_size) | ||
83 | rs[i].result_size = &rs[i].dst_size; | ||
84 | if (GNUNET_OK != | ||
85 | rs[i].conv (rs[i].cls, | ||
86 | result, | ||
87 | j, | ||
88 | rs[i].result_size, | ||
89 | rs[i].dst)) | ||
90 | { | ||
91 | for (unsigned int k = 0; k < i; k++) | ||
92 | if (NULL != rs[k].cleaner) | ||
93 | rs[k].cleaner (rs[k].cls); | ||
94 | return GNUNET_SYSERR; | ||
95 | } | ||
96 | GNUNET_assert (0 != rs[i].num_params); | ||
97 | j += rs[i].num_params; | ||
98 | } | ||
99 | return GNUNET_OK; | ||
100 | } | ||
101 | |||
102 | |||
103 | void | ||
104 | GNUNET_SQ_cleanup_result (struct GNUNET_SQ_ResultSpec *rs) | ||
105 | { | ||
106 | for (unsigned int i = 0; NULL != rs[i].conv; i++) | ||
107 | if (NULL != rs[i].cleaner) | ||
108 | rs[i].cleaner (rs[i].cls); | ||
109 | } | ||
110 | |||
111 | |||
112 | /** | ||
113 | * Reset @a stmt and log error. | ||
114 | * | ||
115 | * @param dbh database handle | ||
116 | * @param stmt statement to reset | ||
117 | */ | ||
118 | void | ||
119 | GNUNET_SQ_reset (sqlite3 *dbh, | ||
120 | sqlite3_stmt *stmt) | ||
121 | { | ||
122 | if (SQLITE_OK != | ||
123 | sqlite3_reset (stmt)) | ||
124 | GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, | ||
125 | "sqlite", | ||
126 | _ ("Failed to reset sqlite statement with error: %s\n"), | ||
127 | sqlite3_errmsg (dbh)); | ||
128 | } | ||
129 | |||
130 | |||
131 | /* end of sq.c */ | ||
diff --git a/src/lib/sq/sq_exec.c b/src/lib/sq/sq_exec.c new file mode 100644 index 000000000..d4690ee99 --- /dev/null +++ b/src/lib/sq/sq_exec.c | |||
@@ -0,0 +1,113 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2018 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file sq/sq_exec.c | ||
22 | * @brief helper functions for executing SQL statements | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_sq_lib.h" | ||
27 | |||
28 | |||
29 | /** | ||
30 | * Create a `struct GNUNET_SQ_ExecuteStatement` where errors are fatal. | ||
31 | * | ||
32 | * @param sql actual SQL statement | ||
33 | * @return initialized struct | ||
34 | */ | ||
35 | struct GNUNET_SQ_ExecuteStatement | ||
36 | GNUNET_SQ_make_execute (const char *sql) | ||
37 | { | ||
38 | struct GNUNET_SQ_ExecuteStatement es = { | ||
39 | .sql = sql, | ||
40 | .ignore_errors = GNUNET_NO | ||
41 | }; | ||
42 | |||
43 | return es; | ||
44 | } | ||
45 | |||
46 | |||
47 | /** | ||
48 | * Create a `struct GNUNET_SQ_ExecuteStatement` where errors should | ||
49 | * be tolerated. | ||
50 | * | ||
51 | * @param sql actual SQL statement | ||
52 | * @return initialized struct | ||
53 | */ | ||
54 | struct GNUNET_SQ_ExecuteStatement | ||
55 | GNUNET_SQ_make_try_execute (const char *sql) | ||
56 | { | ||
57 | struct GNUNET_SQ_ExecuteStatement es = { | ||
58 | .sql = sql, | ||
59 | .ignore_errors = GNUNET_YES | ||
60 | }; | ||
61 | |||
62 | return es; | ||
63 | } | ||
64 | |||
65 | |||
66 | /** | ||
67 | * Request execution of an array of statements @a es from Postgres. | ||
68 | * | ||
69 | * @param dbh database to execute the statements over | ||
70 | * @param es #GNUNET_PQ_PREPARED_STATEMENT_END-terminated array of prepared | ||
71 | * statements. | ||
72 | * @return #GNUNET_OK on success (modulo statements where errors can be ignored) | ||
73 | * #GNUNET_SYSERR on error | ||
74 | */ | ||
75 | enum GNUNET_GenericReturnValue | ||
76 | GNUNET_SQ_exec_statements (sqlite3 *dbh, | ||
77 | const struct GNUNET_SQ_ExecuteStatement *es) | ||
78 | { | ||
79 | for (unsigned int i = 0; NULL != es[i].sql; i++) | ||
80 | { | ||
81 | char *emsg = NULL; | ||
82 | |||
83 | if (SQLITE_OK != | ||
84 | sqlite3_exec (dbh, | ||
85 | es[i].sql, | ||
86 | NULL, | ||
87 | NULL, | ||
88 | &emsg)) | ||
89 | { | ||
90 | if (es[i].ignore_errors) | ||
91 | { | ||
92 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
93 | "Failed to run SQL `%s': %s\n", | ||
94 | es[i].sql, | ||
95 | emsg); | ||
96 | } | ||
97 | else | ||
98 | { | ||
99 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
100 | "Failed to run SQL `%s': %s\n", | ||
101 | es[i].sql, | ||
102 | emsg); | ||
103 | sqlite3_free (emsg); | ||
104 | return GNUNET_SYSERR; | ||
105 | } | ||
106 | sqlite3_free (emsg); | ||
107 | } | ||
108 | } | ||
109 | return GNUNET_OK; | ||
110 | } | ||
111 | |||
112 | |||
113 | /* end of sq_exec */ | ||
diff --git a/src/lib/sq/sq_prepare.c b/src/lib/sq/sq_prepare.c new file mode 100644 index 000000000..d1ca0e8bd --- /dev/null +++ b/src/lib/sq/sq_prepare.c | |||
@@ -0,0 +1,77 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2018 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file sq/sq_prepare.c | ||
22 | * @brief helper functions for executing SQL statements | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_sq_lib.h" | ||
27 | |||
28 | |||
29 | /** | ||
30 | * Create a `struct GNUNET_SQ_PrepareStatement` | ||
31 | * | ||
32 | * @param sql actual SQL statement | ||
33 | * @param pstmt where to store the handle | ||
34 | * @return initialized struct | ||
35 | */ | ||
36 | struct GNUNET_SQ_PrepareStatement | ||
37 | GNUNET_SQ_make_prepare (const char *sql, | ||
38 | sqlite3_stmt **pstmt) | ||
39 | { | ||
40 | struct GNUNET_SQ_PrepareStatement ps = { | ||
41 | .sql = sql, | ||
42 | .pstmt = pstmt | ||
43 | }; | ||
44 | |||
45 | return ps; | ||
46 | } | ||
47 | |||
48 | |||
49 | enum GNUNET_GenericReturnValue | ||
50 | GNUNET_SQ_prepare (sqlite3 *dbh, | ||
51 | const struct GNUNET_SQ_PrepareStatement *ps) | ||
52 | { | ||
53 | for (unsigned int i = 0; NULL != ps[i].sql; i++) | ||
54 | { | ||
55 | const char *epos = NULL; | ||
56 | int ret; | ||
57 | |||
58 | if (SQLITE_OK != | ||
59 | (ret = sqlite3_prepare_v2 (dbh, | ||
60 | ps[i].sql, | ||
61 | strlen (ps[i].sql), | ||
62 | ps[i].pstmt, | ||
63 | &epos))) | ||
64 | { | ||
65 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
66 | "Failed to prepare SQL `%s': error %d at %s\n", | ||
67 | ps[i].sql, | ||
68 | ret, | ||
69 | epos); | ||
70 | return GNUNET_SYSERR; | ||
71 | } | ||
72 | } | ||
73 | return GNUNET_OK; | ||
74 | } | ||
75 | |||
76 | |||
77 | /* end of sq_prepare.c */ | ||
diff --git a/src/lib/sq/sq_query_helper.c b/src/lib/sq/sq_query_helper.c new file mode 100644 index 000000000..ead1b5bdd --- /dev/null +++ b/src/lib/sq/sq_query_helper.c | |||
@@ -0,0 +1,510 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file sq/sq_query_helper.c | ||
22 | * @brief helper functions for queries | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_sq_lib.h" | ||
27 | |||
28 | |||
29 | /** | ||
30 | * Function called to convert input argument into SQL parameters. | ||
31 | * | ||
32 | * @param cls closure | ||
33 | * @param data pointer to input argument | ||
34 | * @param data_len number of bytes in @a data (if applicable) | ||
35 | * @param stmt sqlite statement to bind parameters for | ||
36 | * @param off offset of the argument to bind in @a stmt, numbered from 1, | ||
37 | * so immediately suitable for passing to `sqlite3_bind`-functions. | ||
38 | * @return #GNUNET_SYSERR on error, #GNUNET_OK on success | ||
39 | */ | ||
40 | static int | ||
41 | bind_fixed_blob (void *cls, | ||
42 | const void *data, | ||
43 | size_t data_len, | ||
44 | sqlite3_stmt *stmt, | ||
45 | unsigned int off) | ||
46 | { | ||
47 | if (SQLITE_OK != | ||
48 | sqlite3_bind_blob64 (stmt, | ||
49 | (int) off, | ||
50 | data, | ||
51 | (sqlite3_uint64) data_len, | ||
52 | SQLITE_TRANSIENT)) | ||
53 | return GNUNET_SYSERR; | ||
54 | return GNUNET_OK; | ||
55 | } | ||
56 | |||
57 | |||
58 | /** | ||
59 | * Generate query parameter for a buffer @a ptr of | ||
60 | * @a ptr_size bytes. | ||
61 | * | ||
62 | * @param ptr pointer to the query parameter to pass | ||
63 | * @param ptr_size number of bytes in @a ptr | ||
64 | */ | ||
65 | struct GNUNET_SQ_QueryParam | ||
66 | GNUNET_SQ_query_param_fixed_size (const void *ptr, | ||
67 | size_t ptr_size) | ||
68 | { | ||
69 | struct GNUNET_SQ_QueryParam qp = { | ||
70 | .conv = &bind_fixed_blob, | ||
71 | .data = ptr, | ||
72 | .size = ptr_size, | ||
73 | .num_params = 1 | ||
74 | }; | ||
75 | |||
76 | return qp; | ||
77 | } | ||
78 | |||
79 | |||
80 | /** | ||
81 | * Function called to convert input argument into SQL parameters. | ||
82 | * | ||
83 | * @param cls closure | ||
84 | * @param data pointer to input argument | ||
85 | * @param data_len number of bytes in @a data (if applicable) | ||
86 | * @param stmt sqlite statement to bind parameters for | ||
87 | * @param off offset of the argument to bind in @a stmt, numbered from 1, | ||
88 | * so immediately suitable for passing to `sqlite3_bind`-functions. | ||
89 | * @return #GNUNET_SYSERR on error, #GNUNET_OK on success | ||
90 | */ | ||
91 | static int | ||
92 | bind_string (void *cls, | ||
93 | const void *data, | ||
94 | size_t data_len, | ||
95 | sqlite3_stmt *stmt, | ||
96 | unsigned int off) | ||
97 | { | ||
98 | if (NULL == data) | ||
99 | { | ||
100 | if (SQLITE_OK != | ||
101 | sqlite3_bind_null (stmt, | ||
102 | (int) off)) | ||
103 | return GNUNET_SYSERR; | ||
104 | return GNUNET_OK; | ||
105 | } | ||
106 | if (SQLITE_OK != | ||
107 | sqlite3_bind_text (stmt, | ||
108 | (int) off, | ||
109 | (const char *) data, | ||
110 | -1, | ||
111 | SQLITE_TRANSIENT)) | ||
112 | return GNUNET_SYSERR; | ||
113 | return GNUNET_OK; | ||
114 | } | ||
115 | |||
116 | |||
117 | /** | ||
118 | * Generate query parameter for a string. | ||
119 | * | ||
120 | * @param ptr pointer to the string query parameter to pass | ||
121 | */ | ||
122 | struct GNUNET_SQ_QueryParam | ||
123 | GNUNET_SQ_query_param_string (const char *ptr) | ||
124 | { | ||
125 | struct GNUNET_SQ_QueryParam qp = { | ||
126 | .conv = &bind_string, | ||
127 | .data = ptr, | ||
128 | .num_params = 1 | ||
129 | }; | ||
130 | |||
131 | return qp; | ||
132 | } | ||
133 | |||
134 | |||
135 | /** | ||
136 | * Function called to convert input argument into SQL parameters. | ||
137 | * | ||
138 | * @param cls closure | ||
139 | * @param data pointer to input argument | ||
140 | * @param data_len number of bytes in @a data (if applicable) | ||
141 | * @param stmt sqlite statement to bind parameters for | ||
142 | * @param off offset of the argument to bind in @a stmt, numbered from 1, | ||
143 | * so immediately suitable for passing to `sqlite3_bind`-functions. | ||
144 | * @return #GNUNET_SYSERR on error, #GNUNET_OK on success | ||
145 | */ | ||
146 | static int | ||
147 | bind_rsa_pub (void *cls, | ||
148 | const void *data, | ||
149 | size_t data_len, | ||
150 | sqlite3_stmt *stmt, | ||
151 | unsigned int off) | ||
152 | { | ||
153 | const struct GNUNET_CRYPTO_RsaPublicKey *rsa = data; | ||
154 | void *buf; | ||
155 | size_t buf_size; | ||
156 | |||
157 | GNUNET_break (NULL == cls); | ||
158 | buf_size = GNUNET_CRYPTO_rsa_public_key_encode (rsa, | ||
159 | &buf); | ||
160 | if (SQLITE_OK != | ||
161 | sqlite3_bind_blob64 (stmt, | ||
162 | (int) off, | ||
163 | buf, | ||
164 | (sqlite3_uint64) buf_size, | ||
165 | SQLITE_TRANSIENT)) | ||
166 | { | ||
167 | GNUNET_free (buf); | ||
168 | return GNUNET_SYSERR; | ||
169 | } | ||
170 | GNUNET_free (buf); | ||
171 | return GNUNET_OK; | ||
172 | } | ||
173 | |||
174 | |||
175 | /** | ||
176 | * Generate query parameter for an RSA public key. The | ||
177 | * database must contain a BLOB type in the respective position. | ||
178 | * | ||
179 | * @param x the query parameter to pass. | ||
180 | */ | ||
181 | struct GNUNET_SQ_QueryParam | ||
182 | GNUNET_SQ_query_param_rsa_public_key (const struct | ||
183 | GNUNET_CRYPTO_RsaPublicKey *x) | ||
184 | { | ||
185 | struct GNUNET_SQ_QueryParam qp = { | ||
186 | .conv = &bind_rsa_pub, | ||
187 | .data = x, | ||
188 | .num_params = 1 | ||
189 | }; | ||
190 | |||
191 | return qp; | ||
192 | } | ||
193 | |||
194 | |||
195 | /** | ||
196 | * Function called to convert input argument into SQL parameters. | ||
197 | * | ||
198 | * @param cls closure | ||
199 | * @param data pointer to input argument | ||
200 | * @param data_len number of bytes in @a data (if applicable) | ||
201 | * @param stmt sqlite statement to bind parameters for | ||
202 | * @param off offset of the argument to bind in @a stmt, numbered from 1, | ||
203 | * so immediately suitable for passing to `sqlite3_bind`-functions. | ||
204 | * @return #GNUNET_SYSERR on error, #GNUNET_OK on success | ||
205 | */ | ||
206 | static int | ||
207 | bind_rsa_sig (void *cls, | ||
208 | const void *data, | ||
209 | size_t data_len, | ||
210 | sqlite3_stmt *stmt, | ||
211 | unsigned int off) | ||
212 | { | ||
213 | const struct GNUNET_CRYPTO_RsaSignature *sig = data; | ||
214 | void *buf; | ||
215 | size_t buf_size; | ||
216 | |||
217 | GNUNET_break (NULL == cls); | ||
218 | buf_size = GNUNET_CRYPTO_rsa_signature_encode (sig, | ||
219 | &buf); | ||
220 | if (SQLITE_OK != | ||
221 | sqlite3_bind_blob64 (stmt, | ||
222 | (int) off, | ||
223 | buf, | ||
224 | (sqlite3_uint64) buf_size, | ||
225 | SQLITE_TRANSIENT)) | ||
226 | { | ||
227 | GNUNET_free (buf); | ||
228 | return GNUNET_SYSERR; | ||
229 | } | ||
230 | GNUNET_free (buf); | ||
231 | return GNUNET_OK; | ||
232 | } | ||
233 | |||
234 | |||
235 | /** | ||
236 | * Generate query parameter for an RSA signature. The | ||
237 | * database must contain a BLOB type in the respective position. | ||
238 | * | ||
239 | * @param x the query parameter to pass | ||
240 | */ | ||
241 | struct GNUNET_SQ_QueryParam | ||
242 | GNUNET_SQ_query_param_rsa_signature (const struct GNUNET_CRYPTO_RsaSignature *x) | ||
243 | { | ||
244 | struct GNUNET_SQ_QueryParam qp = { | ||
245 | .conv = &bind_rsa_sig, | ||
246 | .data = x, | ||
247 | .num_params = 1 | ||
248 | }; | ||
249 | |||
250 | return qp; | ||
251 | } | ||
252 | |||
253 | |||
254 | /** | ||
255 | * Function called to convert input argument into SQL parameters. | ||
256 | * | ||
257 | * @param cls closure | ||
258 | * @param data pointer to input argument | ||
259 | * @param data_len number of bytes in @a data (if applicable) | ||
260 | * @param stmt sqlite statement to bind parameters for | ||
261 | * @param off offset of the argument to bind in @a stmt, numbered from 1, | ||
262 | * so immediately suitable for passing to `sqlite3_bind`-functions. | ||
263 | * @return #GNUNET_SYSERR on error, #GNUNET_OK on success | ||
264 | */ | ||
265 | static int | ||
266 | bind_abstime (void *cls, | ||
267 | const void *data, | ||
268 | size_t data_len, | ||
269 | sqlite3_stmt *stmt, | ||
270 | unsigned int off) | ||
271 | { | ||
272 | const struct GNUNET_TIME_Absolute *u = data; | ||
273 | struct GNUNET_TIME_Absolute abs; | ||
274 | |||
275 | abs = *u; | ||
276 | if (abs.abs_value_us > INT64_MAX) | ||
277 | abs.abs_value_us = INT64_MAX; | ||
278 | GNUNET_assert (sizeof(uint64_t) == data_len); | ||
279 | if (SQLITE_OK != | ||
280 | sqlite3_bind_int64 (stmt, | ||
281 | (int) off, | ||
282 | (sqlite3_int64) abs.abs_value_us)) | ||
283 | return GNUNET_SYSERR; | ||
284 | return GNUNET_OK; | ||
285 | } | ||
286 | |||
287 | |||
288 | /** | ||
289 | * Generate query parameter for an absolute time value. | ||
290 | * The database must store a 64-bit integer. | ||
291 | * | ||
292 | * @param x pointer to the query parameter to pass | ||
293 | */ | ||
294 | struct GNUNET_SQ_QueryParam | ||
295 | GNUNET_SQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x) | ||
296 | { | ||
297 | struct GNUNET_SQ_QueryParam qp = { | ||
298 | .conv = &bind_abstime, | ||
299 | .data = x, | ||
300 | .size = sizeof(struct GNUNET_TIME_Absolute), | ||
301 | .num_params = 1 | ||
302 | }; | ||
303 | |||
304 | return qp; | ||
305 | } | ||
306 | |||
307 | |||
308 | /** | ||
309 | * Function called to convert input argument into SQL parameters. | ||
310 | * | ||
311 | * @param cls closure | ||
312 | * @param data pointer to input argument | ||
313 | * @param data_len number of bytes in @a data (if applicable) | ||
314 | * @param stmt sqlite statement to bind parameters for | ||
315 | * @param off offset of the argument to bind in @a stmt, numbered from 1, | ||
316 | * so immediately suitable for passing to `sqlite3_bind`-functions. | ||
317 | * @return #GNUNET_SYSERR on error, #GNUNET_OK on success | ||
318 | */ | ||
319 | static int | ||
320 | bind_nbotime (void *cls, | ||
321 | const void *data, | ||
322 | size_t data_len, | ||
323 | sqlite3_stmt *stmt, | ||
324 | unsigned int off) | ||
325 | { | ||
326 | const struct GNUNET_TIME_AbsoluteNBO *u = data; | ||
327 | struct GNUNET_TIME_Absolute abs; | ||
328 | |||
329 | abs = GNUNET_TIME_absolute_ntoh (*u); | ||
330 | if (abs.abs_value_us > INT64_MAX) | ||
331 | abs.abs_value_us = INT64_MAX; | ||
332 | GNUNET_assert (sizeof(uint64_t) == data_len); | ||
333 | if (SQLITE_OK != | ||
334 | sqlite3_bind_int64 (stmt, | ||
335 | (int) off, | ||
336 | (sqlite3_int64) abs.abs_value_us)) | ||
337 | return GNUNET_SYSERR; | ||
338 | return GNUNET_OK; | ||
339 | } | ||
340 | |||
341 | |||
342 | /** | ||
343 | * Generate query parameter for an absolute time value. | ||
344 | * The database must store a 64-bit integer. | ||
345 | * | ||
346 | * @param x pointer to the query parameter to pass | ||
347 | */ | ||
348 | struct GNUNET_SQ_QueryParam | ||
349 | GNUNET_SQ_query_param_absolute_time_nbo (const struct | ||
350 | GNUNET_TIME_AbsoluteNBO *x) | ||
351 | { | ||
352 | struct GNUNET_SQ_QueryParam qp = { | ||
353 | .conv = &bind_nbotime, | ||
354 | .data = x, | ||
355 | .size = sizeof(struct GNUNET_TIME_AbsoluteNBO), | ||
356 | .num_params = 1 | ||
357 | }; | ||
358 | |||
359 | return qp; | ||
360 | } | ||
361 | |||
362 | |||
363 | /** | ||
364 | * Function called to convert input argument into SQL parameters. | ||
365 | * | ||
366 | * @param cls closure | ||
367 | * @param data pointer to input argument | ||
368 | * @param data_len number of bytes in @a data (if applicable) | ||
369 | * @param stmt sqlite statement to bind parameters for | ||
370 | * @param off offset of the argument to bind in @a stmt, numbered from 1, | ||
371 | * so immediately suitable for passing to `sqlite3_bind`-functions. | ||
372 | * @return #GNUNET_SYSERR on error, #GNUNET_OK on success | ||
373 | */ | ||
374 | static int | ||
375 | bind_u16 (void *cls, | ||
376 | const void *data, | ||
377 | size_t data_len, | ||
378 | sqlite3_stmt *stmt, | ||
379 | unsigned int off) | ||
380 | { | ||
381 | const uint16_t *u = data; | ||
382 | |||
383 | GNUNET_assert (sizeof(uint16_t) == data_len); | ||
384 | if (SQLITE_OK != | ||
385 | sqlite3_bind_int (stmt, | ||
386 | (int) off, | ||
387 | (int) *u)) | ||
388 | return GNUNET_SYSERR; | ||
389 | return GNUNET_OK; | ||
390 | } | ||
391 | |||
392 | |||
393 | /** | ||
394 | * Generate query parameter for an uint16_t in host byte order. | ||
395 | * | ||
396 | * @param x pointer to the query parameter to pass | ||
397 | */ | ||
398 | struct GNUNET_SQ_QueryParam | ||
399 | GNUNET_SQ_query_param_uint16 (const uint16_t *x) | ||
400 | { | ||
401 | struct GNUNET_SQ_QueryParam qp = { | ||
402 | .conv = &bind_u16, | ||
403 | .data = x, | ||
404 | .size = sizeof(uint16_t), | ||
405 | .num_params = 1 | ||
406 | }; | ||
407 | |||
408 | return qp; | ||
409 | } | ||
410 | |||
411 | |||
412 | /** | ||
413 | * Function called to convert input argument into SQL parameters. | ||
414 | * | ||
415 | * @param cls closure | ||
416 | * @param data pointer to input argument | ||
417 | * @param data_len number of bytes in @a data (if applicable) | ||
418 | * @param stmt sqlite statement to bind parameters for | ||
419 | * @param off offset of the argument to bind in @a stmt, numbered from 1, | ||
420 | * so immediately suitable for passing to `sqlite3_bind`-functions. | ||
421 | * @return #GNUNET_SYSERR on error, #GNUNET_OK on success | ||
422 | */ | ||
423 | static int | ||
424 | bind_u32 (void *cls, | ||
425 | const void *data, | ||
426 | size_t data_len, | ||
427 | sqlite3_stmt *stmt, | ||
428 | unsigned int off) | ||
429 | { | ||
430 | const uint32_t *u = data; | ||
431 | |||
432 | GNUNET_assert (sizeof(uint32_t) == data_len); | ||
433 | if (SQLITE_OK != | ||
434 | sqlite3_bind_int64 (stmt, | ||
435 | (int) off, | ||
436 | (sqlite3_int64) * u)) | ||
437 | return GNUNET_SYSERR; | ||
438 | return GNUNET_OK; | ||
439 | } | ||
440 | |||
441 | |||
442 | /** | ||
443 | * Generate query parameter for an uint32_t in host byte order. | ||
444 | * | ||
445 | * @param x pointer to the query parameter to pass | ||
446 | */ | ||
447 | struct GNUNET_SQ_QueryParam | ||
448 | GNUNET_SQ_query_param_uint32 (const uint32_t *x) | ||
449 | { | ||
450 | struct GNUNET_SQ_QueryParam qp = { | ||
451 | .conv = &bind_u32, | ||
452 | .data = x, | ||
453 | .size = sizeof(uint32_t), | ||
454 | .num_params = 1 | ||
455 | }; | ||
456 | |||
457 | return qp; | ||
458 | } | ||
459 | |||
460 | |||
461 | /** | ||
462 | * Function called to convert input argument into SQL parameters. | ||
463 | * | ||
464 | * @param cls closure | ||
465 | * @param data pointer to input argument | ||
466 | * @param data_len number of bytes in @a data (if applicable) | ||
467 | * @param stmt sqlite statement to bind parameters for | ||
468 | * @param off offset of the argument to bind in @a stmt, numbered from 1, | ||
469 | * so immediately suitable for passing to `sqlite3_bind`-functions. | ||
470 | * @return #GNUNET_SYSERR on error, #GNUNET_OK on success | ||
471 | */ | ||
472 | static int | ||
473 | bind_u64 (void *cls, | ||
474 | const void *data, | ||
475 | size_t data_len, | ||
476 | sqlite3_stmt *stmt, | ||
477 | unsigned int off) | ||
478 | { | ||
479 | const uint64_t *u = data; | ||
480 | |||
481 | GNUNET_assert (sizeof(uint64_t) == data_len); | ||
482 | if (SQLITE_OK != | ||
483 | sqlite3_bind_int64 (stmt, | ||
484 | (int) off, | ||
485 | (sqlite3_int64) * u)) | ||
486 | return GNUNET_SYSERR; | ||
487 | return GNUNET_OK; | ||
488 | } | ||
489 | |||
490 | |||
491 | /** | ||
492 | * Generate query parameter for an uint16_t in host byte order. | ||
493 | * | ||
494 | * @param x pointer to the query parameter to pass | ||
495 | */ | ||
496 | struct GNUNET_SQ_QueryParam | ||
497 | GNUNET_SQ_query_param_uint64 (const uint64_t *x) | ||
498 | { | ||
499 | struct GNUNET_SQ_QueryParam qp = { | ||
500 | .conv = &bind_u64, | ||
501 | .data = x, | ||
502 | .size = sizeof(uint64_t), | ||
503 | .num_params = 1 | ||
504 | }; | ||
505 | |||
506 | return qp; | ||
507 | } | ||
508 | |||
509 | |||
510 | /* end of sq_query_helper.c */ | ||
diff --git a/src/lib/sq/sq_result_helper.c b/src/lib/sq/sq_result_helper.c new file mode 100644 index 000000000..5ea3f1e56 --- /dev/null +++ b/src/lib/sq/sq_result_helper.c | |||
@@ -0,0 +1,785 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | Copyright (C) 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file sq/sq_result_helper.c | ||
22 | * @brief helper functions for queries | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_sq_lib.h" | ||
27 | |||
28 | |||
29 | /** | ||
30 | * Extract variable-sized binary data from a Postgres database @a result at row @a row. | ||
31 | * | ||
32 | * @param cls closure | ||
33 | * @param result where to extract data from | ||
34 | * @param column column to extract data from | ||
35 | * @param[in,out] dst_size where to store size of result, may be NULL | ||
36 | * @param[out] dst where to store the result (actually a `void **`) | ||
37 | * @return | ||
38 | * #GNUNET_YES if all results could be extracted | ||
39 | * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) | ||
40 | */ | ||
41 | static int | ||
42 | extract_var_blob (void *cls, | ||
43 | sqlite3_stmt *result, | ||
44 | unsigned int column, | ||
45 | size_t *dst_size, | ||
46 | void *dst) | ||
47 | { | ||
48 | int have; | ||
49 | const void *ret; | ||
50 | void **rdst = (void **) dst; | ||
51 | |||
52 | if (SQLITE_NULL == | ||
53 | sqlite3_column_type (result, | ||
54 | column)) | ||
55 | { | ||
56 | *rdst = NULL; | ||
57 | *dst_size = 0; | ||
58 | return GNUNET_YES; | ||
59 | } | ||
60 | |||
61 | if (SQLITE_BLOB != | ||
62 | sqlite3_column_type (result, | ||
63 | column)) | ||
64 | { | ||
65 | GNUNET_break (0); | ||
66 | return GNUNET_SYSERR; | ||
67 | } | ||
68 | /* sqlite manual says to invoke 'sqlite3_column_blob()' | ||
69 | before calling sqlite3_column_bytes() */ | ||
70 | ret = sqlite3_column_blob (result, | ||
71 | column); | ||
72 | have = sqlite3_column_bytes (result, | ||
73 | column); | ||
74 | if (have < 0) | ||
75 | { | ||
76 | GNUNET_break (0); | ||
77 | return GNUNET_SYSERR; | ||
78 | } | ||
79 | *dst_size = have; | ||
80 | if (0 == have) | ||
81 | { | ||
82 | *rdst = NULL; | ||
83 | return GNUNET_OK; | ||
84 | } | ||
85 | *rdst = GNUNET_malloc (have); | ||
86 | GNUNET_memcpy (*rdst, | ||
87 | ret, | ||
88 | have); | ||
89 | return GNUNET_OK; | ||
90 | } | ||
91 | |||
92 | |||
93 | /** | ||
94 | * Cleanup memory allocated by #extract_var_blob(). | ||
95 | * | ||
96 | * @param cls pointer to pointer of allocation | ||
97 | */ | ||
98 | static void | ||
99 | clean_var_blob (void *cls) | ||
100 | { | ||
101 | void **dptr = (void **) cls; | ||
102 | |||
103 | if (NULL != *dptr) | ||
104 | { | ||
105 | GNUNET_free (*dptr); | ||
106 | *dptr = NULL; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | |||
111 | /** | ||
112 | * Variable-size result expected. | ||
113 | * | ||
114 | * @param[out] dst where to store the result, allocated | ||
115 | * @param[out] sptr where to store the size of @a dst | ||
116 | * @return array entry for the result specification to use | ||
117 | */ | ||
118 | struct GNUNET_SQ_ResultSpec | ||
119 | GNUNET_SQ_result_spec_variable_size (void **dst, | ||
120 | size_t *sptr) | ||
121 | { | ||
122 | struct GNUNET_SQ_ResultSpec rs = { | ||
123 | .conv = &extract_var_blob, | ||
124 | .cleaner = &clean_var_blob, | ||
125 | .dst = dst, | ||
126 | .cls = dst, | ||
127 | .result_size = sptr, | ||
128 | .num_params = 1 | ||
129 | }; | ||
130 | |||
131 | return rs; | ||
132 | } | ||
133 | |||
134 | |||
135 | /** | ||
136 | * Extract fixed-sized binary data from a Postgres database @a result at row @a row. | ||
137 | * | ||
138 | * @param cls closure | ||
139 | * @param result where to extract data from | ||
140 | * @param column column to extract data from | ||
141 | * @param[in,out] dst_size where to store size of result, may be NULL | ||
142 | * @param[out] dst where to store the result | ||
143 | * @return | ||
144 | * #GNUNET_YES if all results could be extracted | ||
145 | * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) | ||
146 | */ | ||
147 | static int | ||
148 | extract_fixed_blob (void *cls, | ||
149 | sqlite3_stmt *result, | ||
150 | unsigned int column, | ||
151 | size_t *dst_size, | ||
152 | void *dst) | ||
153 | { | ||
154 | int have; | ||
155 | const void *ret; | ||
156 | |||
157 | if ((0 == *dst_size) && | ||
158 | (SQLITE_NULL == | ||
159 | sqlite3_column_type (result, | ||
160 | column))) | ||
161 | { | ||
162 | return GNUNET_YES; | ||
163 | } | ||
164 | |||
165 | if (SQLITE_BLOB != | ||
166 | sqlite3_column_type (result, | ||
167 | column)) | ||
168 | { | ||
169 | GNUNET_break (0); | ||
170 | return GNUNET_SYSERR; | ||
171 | } | ||
172 | /* sqlite manual says to invoke 'sqlite3_column_blob()' | ||
173 | before calling sqlite3_column_bytes() */ | ||
174 | ret = sqlite3_column_blob (result, | ||
175 | column); | ||
176 | have = sqlite3_column_bytes (result, | ||
177 | column); | ||
178 | if (*dst_size != have) | ||
179 | { | ||
180 | GNUNET_break (0); | ||
181 | return GNUNET_SYSERR; | ||
182 | } | ||
183 | GNUNET_memcpy (dst, | ||
184 | ret, | ||
185 | have); | ||
186 | return GNUNET_OK; | ||
187 | } | ||
188 | |||
189 | |||
190 | /** | ||
191 | * Fixed-size result expected. | ||
192 | * | ||
193 | * @param[out] dst where to store the result | ||
194 | * @param dst_size number of bytes in @a dst | ||
195 | * @return array entry for the result specification to use | ||
196 | */ | ||
197 | struct GNUNET_SQ_ResultSpec | ||
198 | GNUNET_SQ_result_spec_fixed_size (void *dst, | ||
199 | size_t dst_size) | ||
200 | { | ||
201 | struct GNUNET_SQ_ResultSpec rs = { | ||
202 | .conv = &extract_fixed_blob, | ||
203 | .dst = dst, | ||
204 | .dst_size = dst_size, | ||
205 | .num_params = 1 | ||
206 | }; | ||
207 | |||
208 | return rs; | ||
209 | } | ||
210 | |||
211 | |||
212 | /** | ||
213 | * Extract fixed-sized binary data from a Postgres database @a result at row @a row. | ||
214 | * | ||
215 | * @param cls closure | ||
216 | * @param result where to extract data from | ||
217 | * @param column column to extract data from | ||
218 | * @param[in,out] dst_size where to store size of result, may be NULL | ||
219 | * @param[out] dst where to store the result | ||
220 | * @return | ||
221 | * #GNUNET_YES if all results could be extracted | ||
222 | * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) | ||
223 | */ | ||
224 | static int | ||
225 | extract_utf8_string (void *cls, | ||
226 | sqlite3_stmt *result, | ||
227 | unsigned int column, | ||
228 | size_t *dst_size, | ||
229 | void *dst) | ||
230 | { | ||
231 | const char *text; | ||
232 | char **rdst = dst; | ||
233 | |||
234 | if (SQLITE_NULL == | ||
235 | sqlite3_column_type (result, | ||
236 | column)) | ||
237 | { | ||
238 | *rdst = NULL; | ||
239 | return GNUNET_OK; | ||
240 | } | ||
241 | if (SQLITE_TEXT != | ||
242 | sqlite3_column_type (result, | ||
243 | column)) | ||
244 | { | ||
245 | GNUNET_break (0); | ||
246 | return GNUNET_SYSERR; | ||
247 | } | ||
248 | /* sqlite manual guarantees that 'sqlite3_column_text()' | ||
249 | is 0-terminated */ | ||
250 | text = (const char *) sqlite3_column_text (result, | ||
251 | column); | ||
252 | if (NULL == text) | ||
253 | { | ||
254 | GNUNET_break (0); | ||
255 | return GNUNET_SYSERR; | ||
256 | } | ||
257 | *dst_size = strlen (text) + 1; | ||
258 | *rdst = GNUNET_strdup (text); | ||
259 | return GNUNET_OK; | ||
260 | } | ||
261 | |||
262 | |||
263 | /** | ||
264 | * Cleanup memory allocated by #extract_var_blob(). | ||
265 | * | ||
266 | * @param cls pointer to pointer of allocation | ||
267 | */ | ||
268 | static void | ||
269 | clean_utf8_string (void *cls) | ||
270 | { | ||
271 | char **dptr = (char **) cls; | ||
272 | |||
273 | if (NULL != *dptr) | ||
274 | { | ||
275 | GNUNET_free (*dptr); | ||
276 | *dptr = NULL; | ||
277 | } | ||
278 | } | ||
279 | |||
280 | |||
281 | /** | ||
282 | * 0-terminated string expected. | ||
283 | * | ||
284 | * @param[out] dst where to store the result, allocated | ||
285 | * @return array entry for the result specification to use | ||
286 | */ | ||
287 | struct GNUNET_SQ_ResultSpec | ||
288 | GNUNET_SQ_result_spec_string (char **dst) | ||
289 | { | ||
290 | struct GNUNET_SQ_ResultSpec rs = { | ||
291 | .conv = &extract_utf8_string, | ||
292 | .cleaner = &clean_utf8_string, | ||
293 | .cls = dst, | ||
294 | .dst = dst, | ||
295 | .num_params = 1 | ||
296 | }; | ||
297 | |||
298 | return rs; | ||
299 | } | ||
300 | |||
301 | |||
302 | /** | ||
303 | * Extract data from a Postgres database @a result at row @a row. | ||
304 | * | ||
305 | * @param cls closure | ||
306 | * @param result where to extract data from | ||
307 | * @param column column to extract data from | ||
308 | * @param[in,out] dst_size where to store size of result, may be NULL | ||
309 | * @param[out] dst where to store the result | ||
310 | * @return | ||
311 | * #GNUNET_YES if all results could be extracted | ||
312 | * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) | ||
313 | */ | ||
314 | static int | ||
315 | extract_rsa_pub (void *cls, | ||
316 | sqlite3_stmt *result, | ||
317 | unsigned int column, | ||
318 | size_t *dst_size, | ||
319 | void *dst) | ||
320 | { | ||
321 | struct GNUNET_CRYPTO_RsaPublicKey **pk = dst; | ||
322 | int have; | ||
323 | const void *ret; | ||
324 | |||
325 | if (SQLITE_BLOB != | ||
326 | sqlite3_column_type (result, | ||
327 | column)) | ||
328 | { | ||
329 | GNUNET_break (0); | ||
330 | return GNUNET_SYSERR; | ||
331 | } | ||
332 | /* sqlite manual says to invoke 'sqlite3_column_blob()' | ||
333 | before calling sqlite3_column_bytes() */ | ||
334 | ret = sqlite3_column_blob (result, | ||
335 | column); | ||
336 | have = sqlite3_column_bytes (result, | ||
337 | column); | ||
338 | if (have < 0) | ||
339 | { | ||
340 | GNUNET_break (0); | ||
341 | return GNUNET_SYSERR; | ||
342 | } | ||
343 | |||
344 | *pk = GNUNET_CRYPTO_rsa_public_key_decode (ret, | ||
345 | have); | ||
346 | if (NULL == *pk) | ||
347 | { | ||
348 | GNUNET_break (0); | ||
349 | return GNUNET_SYSERR; | ||
350 | } | ||
351 | return GNUNET_OK; | ||
352 | } | ||
353 | |||
354 | |||
355 | /** | ||
356 | * Function called to clean up memory allocated | ||
357 | * by a #GNUNET_PQ_ResultConverter. | ||
358 | * | ||
359 | * @param cls closure | ||
360 | */ | ||
361 | static void | ||
362 | clean_rsa_pub (void *cls) | ||
363 | { | ||
364 | struct GNUNET_CRYPTO_RsaPublicKey **pk = cls; | ||
365 | |||
366 | if (NULL != *pk) | ||
367 | { | ||
368 | GNUNET_CRYPTO_rsa_public_key_free (*pk); | ||
369 | *pk = NULL; | ||
370 | } | ||
371 | } | ||
372 | |||
373 | |||
374 | /** | ||
375 | * RSA public key expected. | ||
376 | * | ||
377 | * @param[out] rsa where to store the result | ||
378 | * @return array entry for the result specification to use | ||
379 | */ | ||
380 | struct GNUNET_SQ_ResultSpec | ||
381 | GNUNET_SQ_result_spec_rsa_public_key (struct GNUNET_CRYPTO_RsaPublicKey **rsa) | ||
382 | { | ||
383 | struct GNUNET_SQ_ResultSpec rs = { | ||
384 | .conv = &extract_rsa_pub, | ||
385 | .cleaner = &clean_rsa_pub, | ||
386 | .dst = rsa, | ||
387 | .cls = rsa, | ||
388 | .num_params = 1 | ||
389 | }; | ||
390 | |||
391 | return rs; | ||
392 | } | ||
393 | |||
394 | |||
395 | /** | ||
396 | * Extract data from a Postgres database @a result at row @a row. | ||
397 | * | ||
398 | * @param cls closure | ||
399 | * @param result where to extract data from | ||
400 | * @param column column to extract data from | ||
401 | * @param[in,out] dst_size where to store size of result, may be NULL | ||
402 | * @param[out] dst where to store the result | ||
403 | * @return | ||
404 | * #GNUNET_YES if all results could be extracted | ||
405 | * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) | ||
406 | */ | ||
407 | static int | ||
408 | extract_rsa_sig (void *cls, | ||
409 | sqlite3_stmt *result, | ||
410 | unsigned int column, | ||
411 | size_t *dst_size, | ||
412 | void *dst) | ||
413 | { | ||
414 | struct GNUNET_CRYPTO_RsaSignature **sig = dst; | ||
415 | int have; | ||
416 | const void *ret; | ||
417 | |||
418 | if (SQLITE_BLOB != | ||
419 | sqlite3_column_type (result, | ||
420 | column)) | ||
421 | { | ||
422 | GNUNET_break (0); | ||
423 | return GNUNET_SYSERR; | ||
424 | } | ||
425 | /* sqlite manual says to invoke 'sqlite3_column_blob()' | ||
426 | before calling sqlite3_column_bytes() */ | ||
427 | ret = sqlite3_column_blob (result, | ||
428 | column); | ||
429 | have = sqlite3_column_bytes (result, | ||
430 | column); | ||
431 | if (have < 0) | ||
432 | { | ||
433 | GNUNET_break (0); | ||
434 | return GNUNET_SYSERR; | ||
435 | } | ||
436 | |||
437 | *sig = GNUNET_CRYPTO_rsa_signature_decode (ret, | ||
438 | have); | ||
439 | if (NULL == *sig) | ||
440 | { | ||
441 | GNUNET_break (0); | ||
442 | return GNUNET_SYSERR; | ||
443 | } | ||
444 | return GNUNET_OK; | ||
445 | } | ||
446 | |||
447 | |||
448 | /** | ||
449 | * Function called to clean up memory allocated | ||
450 | * by a #GNUNET_PQ_ResultConverter. | ||
451 | * | ||
452 | * @param cls result data to clean up | ||
453 | */ | ||
454 | static void | ||
455 | clean_rsa_sig (void *cls) | ||
456 | { | ||
457 | struct GNUNET_CRYPTO_RsaSignature **sig = cls; | ||
458 | |||
459 | if (NULL != *sig) | ||
460 | { | ||
461 | GNUNET_CRYPTO_rsa_signature_free (*sig); | ||
462 | *sig = NULL; | ||
463 | } | ||
464 | } | ||
465 | |||
466 | |||
467 | /** | ||
468 | * RSA signature expected. | ||
469 | * | ||
470 | * @param[out] sig where to store the result; | ||
471 | * @return array entry for the result specification to use | ||
472 | */ | ||
473 | struct GNUNET_SQ_ResultSpec | ||
474 | GNUNET_SQ_result_spec_rsa_signature (struct GNUNET_CRYPTO_RsaSignature **sig) | ||
475 | { | ||
476 | struct GNUNET_SQ_ResultSpec rs = { | ||
477 | .conv = &extract_rsa_sig, | ||
478 | .cleaner = &clean_rsa_sig, | ||
479 | .dst = sig, | ||
480 | .cls = sig, | ||
481 | .num_params = 1 | ||
482 | }; | ||
483 | |||
484 | return rs; | ||
485 | } | ||
486 | |||
487 | |||
488 | /** | ||
489 | * Extract absolute time value from a Postgres database @a result at row @a row. | ||
490 | * | ||
491 | * @param cls closure | ||
492 | * @param result where to extract data from | ||
493 | * @param column column to extract data from | ||
494 | * @param[in,out] dst_size where to store size of result, may be NULL | ||
495 | * @param[out] dst where to store the result | ||
496 | * @return | ||
497 | * #GNUNET_YES if all results could be extracted | ||
498 | * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) | ||
499 | */ | ||
500 | static int | ||
501 | extract_abs_time (void *cls, | ||
502 | sqlite3_stmt *result, | ||
503 | unsigned int column, | ||
504 | size_t *dst_size, | ||
505 | void *dst) | ||
506 | { | ||
507 | struct GNUNET_TIME_Absolute *u = dst; | ||
508 | struct GNUNET_TIME_Absolute t; | ||
509 | |||
510 | GNUNET_assert (sizeof(uint64_t) == *dst_size); | ||
511 | if (SQLITE_INTEGER != | ||
512 | sqlite3_column_type (result, | ||
513 | column)) | ||
514 | { | ||
515 | GNUNET_break (0); | ||
516 | return GNUNET_SYSERR; | ||
517 | } | ||
518 | t.abs_value_us = (uint64_t) sqlite3_column_int64 (result, | ||
519 | column); | ||
520 | if (INT64_MAX == t.abs_value_us) | ||
521 | t = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
522 | *u = t; | ||
523 | return GNUNET_OK; | ||
524 | } | ||
525 | |||
526 | |||
527 | /** | ||
528 | * Absolute time expected. | ||
529 | * | ||
530 | * @param[out] at where to store the result | ||
531 | * @return array entry for the result specification to use | ||
532 | */ | ||
533 | struct GNUNET_SQ_ResultSpec | ||
534 | GNUNET_SQ_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at) | ||
535 | { | ||
536 | struct GNUNET_SQ_ResultSpec rs = { | ||
537 | .conv = &extract_abs_time, | ||
538 | .dst = at, | ||
539 | .dst_size = sizeof(struct GNUNET_TIME_Absolute), | ||
540 | .num_params = 1 | ||
541 | }; | ||
542 | |||
543 | return rs; | ||
544 | } | ||
545 | |||
546 | |||
547 | /** | ||
548 | * Extract absolute time value in NBO from a Postgres database @a result at row @a row. | ||
549 | * | ||
550 | * @param cls closure | ||
551 | * @param result where to extract data from | ||
552 | * @param column column to extract data from | ||
553 | * @param[in,out] dst_size where to store size of result, may be NULL | ||
554 | * @param[out] dst where to store the result | ||
555 | * @return | ||
556 | * #GNUNET_YES if all results could be extracted | ||
557 | * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) | ||
558 | */ | ||
559 | static int | ||
560 | extract_abs_time_nbo (void *cls, | ||
561 | sqlite3_stmt *result, | ||
562 | unsigned int column, | ||
563 | size_t *dst_size, | ||
564 | void *dst) | ||
565 | { | ||
566 | struct GNUNET_TIME_AbsoluteNBO *u = dst; | ||
567 | struct GNUNET_TIME_Absolute t; | ||
568 | |||
569 | GNUNET_assert (sizeof(uint64_t) == *dst_size); | ||
570 | if (SQLITE_INTEGER != | ||
571 | sqlite3_column_type (result, | ||
572 | column)) | ||
573 | { | ||
574 | GNUNET_break (0); | ||
575 | return GNUNET_SYSERR; | ||
576 | } | ||
577 | t.abs_value_us = (uint64_t) sqlite3_column_int64 (result, | ||
578 | column); | ||
579 | if (INT64_MAX == t.abs_value_us) | ||
580 | t = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
581 | *u = GNUNET_TIME_absolute_hton (t); | ||
582 | return GNUNET_OK; | ||
583 | } | ||
584 | |||
585 | |||
586 | /** | ||
587 | * Absolute time expected. | ||
588 | * | ||
589 | * @param[out] at where to store the result | ||
590 | * @return array entry for the result specification to use | ||
591 | */ | ||
592 | struct GNUNET_SQ_ResultSpec | ||
593 | GNUNET_SQ_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at) | ||
594 | { | ||
595 | struct GNUNET_SQ_ResultSpec rs = { | ||
596 | .conv = &extract_abs_time_nbo, | ||
597 | .dst = at, | ||
598 | .dst_size = sizeof(struct GNUNET_TIME_AbsoluteNBO), | ||
599 | .num_params = 1 | ||
600 | }; | ||
601 | |||
602 | return rs; | ||
603 | } | ||
604 | |||
605 | |||
606 | /** | ||
607 | * Extract 16-bit integer from a Postgres database @a result at row @a row. | ||
608 | * | ||
609 | * @param cls closure | ||
610 | * @param result where to extract data from | ||
611 | * @param column column to extract data from | ||
612 | * @param[in,out] dst_size where to store size of result, may be NULL | ||
613 | * @param[out] dst where to store the result | ||
614 | * @return | ||
615 | * #GNUNET_YES if all results could be extracted | ||
616 | * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) | ||
617 | */ | ||
618 | static int | ||
619 | extract_uint16 (void *cls, | ||
620 | sqlite3_stmt *result, | ||
621 | unsigned int column, | ||
622 | size_t *dst_size, | ||
623 | void *dst) | ||
624 | { | ||
625 | uint64_t v; | ||
626 | uint16_t *u = dst; | ||
627 | |||
628 | GNUNET_assert (sizeof(uint16_t) == *dst_size); | ||
629 | if (SQLITE_INTEGER != | ||
630 | sqlite3_column_type (result, | ||
631 | column)) | ||
632 | { | ||
633 | GNUNET_break (0); | ||
634 | return GNUNET_SYSERR; | ||
635 | } | ||
636 | v = (uint64_t) sqlite3_column_int64 (result, | ||
637 | column); | ||
638 | if (v > UINT16_MAX) | ||
639 | { | ||
640 | GNUNET_break (0); | ||
641 | return GNUNET_SYSERR; | ||
642 | } | ||
643 | *u = (uint16_t) v; | ||
644 | return GNUNET_OK; | ||
645 | } | ||
646 | |||
647 | |||
648 | /** | ||
649 | * uint16_t expected. | ||
650 | * | ||
651 | * @param[out] u16 where to store the result | ||
652 | * @return array entry for the result specification to use | ||
653 | */ | ||
654 | struct GNUNET_SQ_ResultSpec | ||
655 | GNUNET_SQ_result_spec_uint16 (uint16_t *u16) | ||
656 | { | ||
657 | struct GNUNET_SQ_ResultSpec rs = { | ||
658 | .conv = &extract_uint16, | ||
659 | .dst = u16, | ||
660 | .dst_size = sizeof(uint16_t), | ||
661 | .num_params = 1 | ||
662 | }; | ||
663 | |||
664 | return rs; | ||
665 | } | ||
666 | |||
667 | |||
668 | /** | ||
669 | * Extract 32-bit integer from a Postgres database @a result at row @a row. | ||
670 | * | ||
671 | * @param cls closure | ||
672 | * @param result where to extract data from | ||
673 | * @param column column to extract data from | ||
674 | * @param[in,out] dst_size where to store size of result, may be NULL | ||
675 | * @param[out] dst where to store the result | ||
676 | * @return | ||
677 | * #GNUNET_YES if all results could be extracted | ||
678 | * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) | ||
679 | */ | ||
680 | static int | ||
681 | extract_uint32 (void *cls, | ||
682 | sqlite3_stmt *result, | ||
683 | unsigned int column, | ||
684 | size_t *dst_size, | ||
685 | void *dst) | ||
686 | { | ||
687 | uint64_t v; | ||
688 | uint32_t *u = dst; | ||
689 | |||
690 | GNUNET_assert (sizeof(uint32_t) == *dst_size); | ||
691 | if (SQLITE_INTEGER != | ||
692 | sqlite3_column_type (result, | ||
693 | column)) | ||
694 | { | ||
695 | GNUNET_break (0); | ||
696 | return GNUNET_SYSERR; | ||
697 | } | ||
698 | v = (uint64_t) sqlite3_column_int64 (result, | ||
699 | column); | ||
700 | if (v > UINT32_MAX) | ||
701 | { | ||
702 | GNUNET_break (0); | ||
703 | return GNUNET_SYSERR; | ||
704 | } | ||
705 | *u = (uint32_t) v; | ||
706 | return GNUNET_OK; | ||
707 | } | ||
708 | |||
709 | |||
710 | /** | ||
711 | * uint32_t expected. | ||
712 | * | ||
713 | * @param[out] u32 where to store the result | ||
714 | * @return array entry for the result specification to use | ||
715 | */ | ||
716 | struct GNUNET_SQ_ResultSpec | ||
717 | GNUNET_SQ_result_spec_uint32 (uint32_t *u32) | ||
718 | { | ||
719 | struct GNUNET_SQ_ResultSpec rs = { | ||
720 | .conv = &extract_uint32, | ||
721 | .dst = u32, | ||
722 | .dst_size = sizeof(uint32_t), | ||
723 | .num_params = 1 | ||
724 | }; | ||
725 | |||
726 | return rs; | ||
727 | } | ||
728 | |||
729 | |||
730 | /** | ||
731 | * Extract 64-bit integer from a Postgres database @a result at row @a row. | ||
732 | * | ||
733 | * @param cls closure | ||
734 | * @param result where to extract data from | ||
735 | * @param column column to extract data from | ||
736 | * @param[in,out] dst_size where to store size of result, may be NULL | ||
737 | * @param[out] dst where to store the result | ||
738 | * @return | ||
739 | * #GNUNET_YES if all results could be extracted | ||
740 | * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) | ||
741 | */ | ||
742 | static int | ||
743 | extract_uint64 (void *cls, | ||
744 | sqlite3_stmt *result, | ||
745 | unsigned int column, | ||
746 | size_t *dst_size, | ||
747 | void *dst) | ||
748 | { | ||
749 | uint64_t *u = dst; | ||
750 | |||
751 | GNUNET_assert (sizeof(uint64_t) == *dst_size); | ||
752 | if (SQLITE_INTEGER != | ||
753 | sqlite3_column_type (result, | ||
754 | column)) | ||
755 | { | ||
756 | GNUNET_break (0); | ||
757 | return GNUNET_SYSERR; | ||
758 | } | ||
759 | *u = (uint64_t) sqlite3_column_int64 (result, | ||
760 | column); | ||
761 | return GNUNET_OK; | ||
762 | } | ||
763 | |||
764 | |||
765 | /** | ||
766 | * uint64_t expected. | ||
767 | * | ||
768 | * @param[out] u64 where to store the result | ||
769 | * @return array entry for the result specification to use | ||
770 | */ | ||
771 | struct GNUNET_SQ_ResultSpec | ||
772 | GNUNET_SQ_result_spec_uint64 (uint64_t *u64) | ||
773 | { | ||
774 | struct GNUNET_SQ_ResultSpec rs = { | ||
775 | .conv = &extract_uint64, | ||
776 | .dst = u64, | ||
777 | .dst_size = sizeof(uint64_t), | ||
778 | .num_params = 1 | ||
779 | }; | ||
780 | |||
781 | return rs; | ||
782 | } | ||
783 | |||
784 | |||
785 | /* end of sq_result_helper.c */ | ||
diff --git a/src/lib/sq/test_sq.c b/src/lib/sq/test_sq.c new file mode 100644 index 000000000..292de5f34 --- /dev/null +++ b/src/lib/sq/test_sq.c | |||
@@ -0,0 +1,291 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet | ||
3 | (C) 2015, 2016, 2017 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | /** | ||
21 | * @file sq/test_sq.c | ||
22 | * @brief Tests for sqlite3 convenience API | ||
23 | * @author Christian Grothoff | ||
24 | */ | ||
25 | #include "platform.h" | ||
26 | #include "gnunet_util_lib.h" | ||
27 | #include "gnunet_sq_lib.h" | ||
28 | |||
29 | |||
30 | /** | ||
31 | * @brief Prepare a SQL statement | ||
32 | * | ||
33 | * @param dbh handle to the database | ||
34 | * @param zSql SQL statement, UTF-8 encoded | ||
35 | * @param[out] ppStmt set to the prepared statement | ||
36 | * @return 0 on success | ||
37 | */ | ||
38 | static int | ||
39 | sq_prepare (sqlite3 *dbh, | ||
40 | const char *zSql, | ||
41 | sqlite3_stmt **ppStmt) | ||
42 | { | ||
43 | char *dummy; | ||
44 | int result; | ||
45 | |||
46 | result = sqlite3_prepare_v2 (dbh, | ||
47 | zSql, | ||
48 | strlen (zSql), | ||
49 | ppStmt, | ||
50 | (const char **) &dummy); | ||
51 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
52 | "Prepared `%s' / %p: %d\n", | ||
53 | zSql, | ||
54 | *ppStmt, | ||
55 | result); | ||
56 | return result; | ||
57 | } | ||
58 | |||
59 | |||
60 | /** | ||
61 | * Run actual test queries. | ||
62 | * | ||
63 | * @return 0 on success | ||
64 | */ | ||
65 | static int | ||
66 | run_queries (sqlite3 *dbh) | ||
67 | { | ||
68 | struct GNUNET_CRYPTO_RsaPublicKey *pub; | ||
69 | struct GNUNET_CRYPTO_RsaPublicKey *pub2 = NULL; | ||
70 | struct GNUNET_CRYPTO_RsaSignature *sig; | ||
71 | struct GNUNET_CRYPTO_RsaSignature *sig2 = NULL; | ||
72 | struct GNUNET_TIME_Absolute abs_time = GNUNET_TIME_absolute_get (); | ||
73 | struct GNUNET_TIME_Absolute abs_time2; | ||
74 | struct GNUNET_TIME_Absolute forever = GNUNET_TIME_UNIT_FOREVER_ABS; | ||
75 | struct GNUNET_TIME_Absolute forever2; | ||
76 | struct GNUNET_HashCode hc; | ||
77 | struct GNUNET_HashCode hc2; | ||
78 | sqlite3_stmt *stmt; | ||
79 | struct GNUNET_CRYPTO_RsaPrivateKey *priv; | ||
80 | const char msg[] = "hello"; | ||
81 | void *msg2; | ||
82 | struct GNUNET_HashCode hmsg; | ||
83 | size_t msg2_len; | ||
84 | uint16_t u16; | ||
85 | uint16_t u162; | ||
86 | uint32_t u32; | ||
87 | uint32_t u322; | ||
88 | uint64_t u64; | ||
89 | uint64_t u642; | ||
90 | |||
91 | priv = GNUNET_CRYPTO_rsa_private_key_create (1024); | ||
92 | pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv); | ||
93 | memset (&hmsg, 42, sizeof(hmsg)); | ||
94 | sig = GNUNET_CRYPTO_rsa_sign_fdh (priv, | ||
95 | &hmsg, | ||
96 | sizeof (hmsg)); | ||
97 | u16 = 16; | ||
98 | u32 = 32; | ||
99 | u64 = 64; | ||
100 | /* FIXME: test GNUNET_SQ_result_spec_variable_size */ | ||
101 | |||
102 | sq_prepare (dbh, | ||
103 | "INSERT INTO test_sq (" | ||
104 | " pub" | ||
105 | ",sig" | ||
106 | ",abs_time" | ||
107 | ",forever" | ||
108 | ",hash" | ||
109 | ",vsize" | ||
110 | ",u16" | ||
111 | ",u32" | ||
112 | ",u64" | ||
113 | ") VALUES " | ||
114 | "($1, $2, $3, $4, $5, $6," | ||
115 | "$7, $8, $9);", | ||
116 | &stmt); | ||
117 | { | ||
118 | struct GNUNET_SQ_QueryParam params_insert[] = { | ||
119 | GNUNET_SQ_query_param_rsa_public_key (pub), | ||
120 | GNUNET_SQ_query_param_rsa_signature (sig), | ||
121 | GNUNET_SQ_query_param_absolute_time (&abs_time), | ||
122 | GNUNET_SQ_query_param_absolute_time (&forever), | ||
123 | GNUNET_SQ_query_param_auto_from_type (&hc), | ||
124 | GNUNET_SQ_query_param_fixed_size (msg, strlen (msg)), | ||
125 | GNUNET_SQ_query_param_uint16 (&u16), | ||
126 | GNUNET_SQ_query_param_uint32 (&u32), | ||
127 | GNUNET_SQ_query_param_uint64 (&u64), | ||
128 | GNUNET_SQ_query_param_end | ||
129 | }; | ||
130 | |||
131 | GNUNET_assert (GNUNET_OK == | ||
132 | GNUNET_SQ_bind (stmt, | ||
133 | params_insert)); | ||
134 | if (SQLITE_DONE != | ||
135 | sqlite3_step (stmt)) | ||
136 | { | ||
137 | GNUNET_CRYPTO_rsa_signature_free (sig); | ||
138 | GNUNET_CRYPTO_rsa_private_key_free (priv); | ||
139 | GNUNET_CRYPTO_rsa_public_key_free (pub); | ||
140 | return 1; | ||
141 | } | ||
142 | sqlite3_reset (stmt); | ||
143 | } | ||
144 | sqlite3_finalize (stmt); | ||
145 | |||
146 | sq_prepare (dbh, | ||
147 | "SELECT" | ||
148 | " pub" | ||
149 | ",sig" | ||
150 | ",abs_time" | ||
151 | ",forever" | ||
152 | ",hash" | ||
153 | ",vsize" | ||
154 | ",u16" | ||
155 | ",u32" | ||
156 | ",u64" | ||
157 | " FROM test_sq" | ||
158 | " ORDER BY abs_time DESC " | ||
159 | " LIMIT 1;", | ||
160 | &stmt); | ||
161 | { | ||
162 | struct GNUNET_SQ_QueryParam params_select[] = { | ||
163 | GNUNET_SQ_query_param_end | ||
164 | }; | ||
165 | struct GNUNET_SQ_ResultSpec results_select[] = { | ||
166 | GNUNET_SQ_result_spec_rsa_public_key (&pub2), | ||
167 | GNUNET_SQ_result_spec_rsa_signature (&sig2), | ||
168 | GNUNET_SQ_result_spec_absolute_time (&abs_time2), | ||
169 | GNUNET_SQ_result_spec_absolute_time (&forever2), | ||
170 | GNUNET_SQ_result_spec_auto_from_type (&hc2), | ||
171 | GNUNET_SQ_result_spec_variable_size (&msg2, &msg2_len), | ||
172 | GNUNET_SQ_result_spec_uint16 (&u162), | ||
173 | GNUNET_SQ_result_spec_uint32 (&u322), | ||
174 | GNUNET_SQ_result_spec_uint64 (&u642), | ||
175 | GNUNET_SQ_result_spec_end | ||
176 | }; | ||
177 | |||
178 | GNUNET_assert (GNUNET_OK == | ||
179 | GNUNET_SQ_bind (stmt, | ||
180 | params_select)); | ||
181 | if (SQLITE_ROW != | ||
182 | sqlite3_step (stmt)) | ||
183 | { | ||
184 | GNUNET_break (0); | ||
185 | sqlite3_finalize (stmt); | ||
186 | GNUNET_CRYPTO_rsa_signature_free (sig); | ||
187 | GNUNET_CRYPTO_rsa_private_key_free (priv); | ||
188 | GNUNET_CRYPTO_rsa_public_key_free (pub); | ||
189 | return 1; | ||
190 | } | ||
191 | GNUNET_assert (GNUNET_OK == | ||
192 | GNUNET_SQ_extract_result (stmt, | ||
193 | results_select)); | ||
194 | GNUNET_break (abs_time.abs_value_us == abs_time2.abs_value_us); | ||
195 | GNUNET_break (forever.abs_value_us == forever2.abs_value_us); | ||
196 | GNUNET_break (0 == | ||
197 | GNUNET_memcmp (&hc, | ||
198 | &hc2)); | ||
199 | GNUNET_break (0 == | ||
200 | GNUNET_CRYPTO_rsa_signature_cmp (sig, | ||
201 | sig2)); | ||
202 | GNUNET_break (0 == | ||
203 | GNUNET_CRYPTO_rsa_public_key_cmp (pub, | ||
204 | pub2)); | ||
205 | GNUNET_break (strlen (msg) == msg2_len); | ||
206 | GNUNET_break (0 == | ||
207 | strncmp (msg, | ||
208 | msg2, | ||
209 | msg2_len)); | ||
210 | GNUNET_break (16 == u162); | ||
211 | GNUNET_break (32 == u322); | ||
212 | GNUNET_break (64 == u642); | ||
213 | GNUNET_SQ_cleanup_result (results_select); | ||
214 | sqlite3_reset (stmt); | ||
215 | } | ||
216 | sqlite3_finalize (stmt); | ||
217 | |||
218 | GNUNET_CRYPTO_rsa_signature_free (sig); | ||
219 | GNUNET_CRYPTO_rsa_private_key_free (priv); | ||
220 | GNUNET_CRYPTO_rsa_public_key_free (pub); | ||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | |||
225 | int | ||
226 | main (int argc, | ||
227 | const char *const argv[]) | ||
228 | { | ||
229 | sqlite3 *dbh; | ||
230 | int ret; | ||
231 | |||
232 | GNUNET_log_setup ("test-sq", | ||
233 | "WARNING", | ||
234 | NULL); | ||
235 | if (SQLITE_OK != | ||
236 | sqlite3_open ("test.db", | ||
237 | &dbh)) | ||
238 | { | ||
239 | fprintf (stderr, | ||
240 | "Cannot run test, sqlite3 initialization failed\n"); | ||
241 | GNUNET_break (0); | ||
242 | return 77; /* Signal test was skipped... */ | ||
243 | } | ||
244 | |||
245 | if (SQLITE_OK != | ||
246 | sqlite3_exec (dbh, | ||
247 | "CREATE TEMPORARY TABLE IF NOT EXISTS test_sq (" | ||
248 | " pub BYTEA NOT NULL" | ||
249 | ",sig BYTEA NOT NULL" | ||
250 | ",abs_time INT8 NOT NULL" | ||
251 | ",forever INT8 NOT NULL" | ||
252 | ",hash BYTEA NOT NULL" | ||
253 | ",vsize VARCHAR NOT NULL" | ||
254 | ",u16 INT2 NOT NULL" | ||
255 | ",u32 INT4 NOT NULL" | ||
256 | ",u64 INT8 NOT NULL" | ||
257 | ")", | ||
258 | NULL, NULL, NULL)) | ||
259 | { | ||
260 | fprintf (stderr, | ||
261 | "Failed to create table\n"); | ||
262 | GNUNET_break (SQLITE_OK == | ||
263 | sqlite3_close (dbh)); | ||
264 | if (0 != unlink ("test.db")) | ||
265 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, | ||
266 | "unlink", | ||
267 | "test.db"); | ||
268 | return 1; | ||
269 | } | ||
270 | |||
271 | ret = run_queries (dbh); | ||
272 | if (SQLITE_OK != | ||
273 | sqlite3_exec (dbh, | ||
274 | "DROP TABLE test_sq", | ||
275 | NULL, NULL, NULL)) | ||
276 | { | ||
277 | fprintf (stderr, | ||
278 | "Failed to drop table\n"); | ||
279 | ret = 1; | ||
280 | } | ||
281 | GNUNET_break (SQLITE_OK == | ||
282 | sqlite3_close (dbh)); | ||
283 | if (0 != unlink ("test.db")) | ||
284 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, | ||
285 | "unlink", | ||
286 | "test.db"); | ||
287 | return ret; | ||
288 | } | ||
289 | |||
290 | |||
291 | /* end of test_sq.c */ | ||