test_pq.c (8201B)
1 /* 2 This file is part of TALER 3 (C) 2024 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @file pq/test_pq.c 18 * @brief Tests for Postgres convenience API 19 * @author Christian Grothoff <christian@grothoff.org> 20 */ 21 #include <donau_config.h> 22 #include <taler/taler_util.h> 23 #include <taler/taler_pq_lib.h> 24 25 26 /** 27 * Setup prepared statements. 28 * 29 * @param db database handle to initialize 30 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure 31 */ 32 static enum GNUNET_GenericReturnValue 33 postgres_prepare (struct GNUNET_PQ_Context *db) 34 { 35 struct GNUNET_PQ_PreparedStatement ps[] = { 36 GNUNET_PQ_make_prepare ("test_insert", 37 "INSERT INTO test_pq (" 38 " tamount" 39 ",json" 40 ",aamount" 41 ",tamountc" 42 ") VALUES " 43 "($1, $2, $3, $4);"), 44 GNUNET_PQ_make_prepare ("test_select", 45 "SELECT" 46 " tamount" 47 ",json" 48 ",aamount" 49 ",tamountc" 50 " FROM test_pq;"), 51 GNUNET_PQ_PREPARED_STATEMENT_END 52 }; 53 54 return GNUNET_PQ_prepare_statements (db, 55 ps); 56 } 57 58 59 /** 60 * Run actual test queries. 61 * 62 * @return 0 on success 63 */ 64 static int 65 run_queries (struct GNUNET_PQ_Context *conn) 66 { 67 struct TALER_Amount tamount; 68 struct TALER_Amount aamount[3]; 69 struct TALER_Amount tamountc; 70 json_t *json; 71 72 GNUNET_assert (GNUNET_OK == 73 TALER_string_to_amount ("EUR:5.3", 74 &aamount[0])); 75 GNUNET_assert (GNUNET_OK == 76 TALER_string_to_amount ("EUR:6.4", 77 &aamount[1])); 78 GNUNET_assert (GNUNET_OK == 79 TALER_string_to_amount ("EUR:7.5", 80 &aamount[2])); 81 GNUNET_assert (GNUNET_OK == 82 TALER_string_to_amount ("EUR:7.7", 83 &tamount)); 84 GNUNET_assert (GNUNET_OK == 85 TALER_string_to_amount ("FOO:8.7", 86 &tamountc)); 87 json = json_object (); 88 GNUNET_assert (NULL != json); 89 GNUNET_assert (0 == 90 json_object_set_new (json, 91 "foo", 92 json_integer (42))); 93 { 94 struct GNUNET_PQ_QueryParam params_insert[] = { 95 TALER_PQ_query_param_amount (conn, 96 &tamount), 97 TALER_PQ_query_param_json (json), 98 TALER_PQ_query_param_array_amount (3, 99 aamount, 100 conn), 101 TALER_PQ_query_param_amount_with_currency (conn, 102 &tamountc), 103 GNUNET_PQ_query_param_end 104 }; 105 PGresult *result; 106 107 result = GNUNET_PQ_exec_prepared (conn, 108 "test_insert", 109 params_insert); 110 GNUNET_PQ_cleanup_query_params_closures (params_insert); 111 if (PGRES_COMMAND_OK != PQresultStatus (result)) 112 { 113 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 114 "Database failure: %s\n", 115 PQresultErrorMessage (result)); 116 PQclear (result); 117 return 1; 118 } 119 PQclear (result); 120 json_decref (json); 121 } 122 { 123 struct TALER_Amount tamount2; 124 struct TALER_Amount tamountc2; 125 struct TALER_Amount *pamount; 126 size_t npamount; 127 json_t *json2; 128 struct GNUNET_PQ_QueryParam params_select[] = { 129 GNUNET_PQ_query_param_end 130 }; 131 struct GNUNET_PQ_ResultSpec results_select[] = { 132 TALER_PQ_result_spec_amount ("tamount", 133 "EUR", 134 &tamount2), 135 TALER_PQ_result_spec_json ("json", 136 &json2), 137 TALER_PQ_result_spec_array_amount (conn, 138 "aamount", 139 "EUR", 140 &npamount, 141 &pamount), 142 TALER_PQ_result_spec_amount_with_currency ("tamountc", 143 &tamountc2), 144 GNUNET_PQ_result_spec_end 145 }; 146 147 if (1 != 148 GNUNET_PQ_eval_prepared_singleton_select (conn, 149 "test_select", 150 params_select, 151 results_select)) 152 { 153 GNUNET_break (0); 154 return 1; 155 } 156 GNUNET_break (0 == 157 TALER_amount_cmp (&tamount, 158 &tamount2)); 159 GNUNET_break (42 == 160 json_integer_value (json_object_get (json2, 161 "foo"))); 162 GNUNET_break (3 == npamount); 163 for (size_t i = 0; i < 3; i++) 164 { 165 GNUNET_break (0 == 166 TALER_amount_cmp (&aamount[i], 167 &pamount[i])); 168 } 169 GNUNET_break (0 == 170 TALER_amount_cmp (&tamountc, 171 &tamountc2)); 172 GNUNET_PQ_cleanup_result (results_select); 173 } 174 return 0; 175 } 176 177 178 int 179 main (int argc, 180 const char *const argv[]) 181 { 182 struct GNUNET_PQ_ExecuteStatement es[] = { 183 GNUNET_PQ_make_execute ("DO $$ " 184 " BEGIN" 185 " CREATE TYPE taler_amount AS" 186 " (val INT8, frac INT4);" 187 " EXCEPTION" 188 " WHEN duplicate_object THEN null;" 189 " END " 190 "$$;"), 191 GNUNET_PQ_make_execute ("DO $$ " 192 " BEGIN" 193 " CREATE TYPE taler_amount_currency AS" 194 " (val INT8, frac INT4, curr VARCHAR(12));" 195 " EXCEPTION" 196 " WHEN duplicate_object THEN null;" 197 " END " 198 "$$;"), 199 GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS test_pq (" 200 " tamount taler_amount NOT NULL" 201 ",json VARCHAR NOT NULL" 202 ",aamount taler_amount[]" 203 ",tamountc taler_amount_currency" 204 ")"), 205 GNUNET_PQ_EXECUTE_STATEMENT_END 206 }; 207 struct GNUNET_PQ_Context *conn; 208 int ret; 209 210 (void) argc; 211 (void) argv; 212 GNUNET_log_setup ("test-pq", 213 "WARNING", 214 NULL); 215 conn = GNUNET_PQ_connect ("postgres:///donaucheck", 216 NULL, 217 es, 218 NULL); 219 if (NULL == conn) 220 return 77; 221 if (GNUNET_OK != 222 postgres_prepare (conn)) 223 { 224 GNUNET_break (0); 225 GNUNET_PQ_disconnect (conn); 226 return 1; 227 } 228 229 ret = run_queries (conn); 230 { 231 struct GNUNET_PQ_ExecuteStatement ds[] = { 232 GNUNET_PQ_make_execute ("DROP TABLE test_pq"), 233 GNUNET_PQ_EXECUTE_STATEMENT_END 234 }; 235 236 if (GNUNET_OK != 237 GNUNET_PQ_exec_statements (conn, 238 ds)) 239 { 240 fprintf (stderr, 241 "Failed to drop table\n"); 242 GNUNET_PQ_disconnect (conn); 243 return 1; 244 } 245 } 246 GNUNET_PQ_disconnect (conn); 247 return ret; 248 } 249 250 251 /* end of test_pq.c */