c661d54560e1230c0e90b99907eb714de00f8f7e
[pthrlib.git] / test_dbi.c
1 /* Test the database interface.
2  * Copyright (C) 2002 Richard W.M. Jones <rich@annexia.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  *
18  * $Id: test_dbi.c,v 1.6 2002/12/09 10:43:27 rich Exp $
19  */
20
21 #include "config.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <assert.h>
26
27 #ifdef HAVE_STRING_H
28 #include <string.h>
29 #endif
30
31 #include <pool.h>
32
33 #include "pthr_pseudothread.h"
34 #include "pthr_dbi.h"
35
36 static pool test_pool;
37 static pseudothread test_pth;
38
39 static void
40 do_test (void *data)
41 {
42   db_handle dbh;
43   st_handle sth;
44   int userid, rownum;
45   char *alias, *username;
46   struct dbi_timestamp ts;
47   struct dbi_interval inv;
48
49   /* Open a connection to the database. */
50   dbh = new_db_handle (test_pool, "", DBI_THROW_ERRORS);
51   if (!dbh)
52     pth_die ("failed to connect to the database, check PGHOST, etc.");
53
54   /* Create some tables and some data. */
55   sth = st_prepare_cached
56     (dbh,
57      "create temporary table tdbi_users "
58      "  (userid int4, "
59      "   username text not null, "
60      "   age int2 not null, "
61      "   last_login date, "
62      "   unique (userid), "
63      "   unique (username))");
64   st_execute (sth);
65
66   sth = st_prepare_cached
67     (dbh,
68      "create temporary table tdbi_aliases "
69      "  (userid int4 references tdbi_users (userid), "
70      "   alias text not null)");
71   st_execute (sth);
72
73   sth = st_prepare_cached
74     (dbh,
75      "insert into tdbi_users (userid, username, age) values (?, ?, ?)",
76      DBI_INT, DBI_STRING, DBI_INT);
77   st_execute (sth, 1, "rich", 30);
78   st_execute (sth, 2, "anna", 45);
79   st_execute (sth, 3, "bob", 55);
80   st_execute (sth, 4, "dan", 24);
81
82   sth = st_prepare_cached
83     (dbh,
84      "insert into tdbi_aliases (userid, alias) values (?, ?)",
85      DBI_INT, DBI_STRING);
86   st_execute (sth, 1, "richard");
87   st_execute (sth, 1, "richie");
88   st_execute (sth, 1, "richy");
89   st_execute (sth, 2, "ann");
90   st_execute (sth, 2, "annie");
91   st_execute (sth, 3, "robert");
92   st_execute (sth, 3, "bobbie");
93   st_execute (sth, 3, "bobby");
94
95   /* Select out some results. */
96   sth = st_prepare_cached
97     (dbh,
98      "select u.userid, u.username, a.alias "
99      "from tdbi_users u, tdbi_aliases a "
100      "where u.userid = a.userid "
101      "order by 3");
102   st_execute (sth);
103
104   st_bind (sth, 0, userid, DBI_INT);
105   st_bind (sth, 1, username, DBI_STRING);
106   st_bind (sth, 2, alias, DBI_STRING);
107
108   rownum = 0;
109   while (st_fetch (sth))
110     {
111       switch (rownum)
112         {
113         case 0:
114           assert (userid == 2 &&
115                   strcmp (username, "anna") == 0 &&
116                   strcmp (alias, "ann") == 0);
117           break;
118         case 1:
119           assert (userid == 2 &&
120                   strcmp (username, "anna") == 0 &&
121                   strcmp (alias, "annie") == 0);
122           break;
123         case 2:
124           assert (userid == 3 &&
125                   strcmp (username, "bob") == 0 &&
126                   strcmp (alias, "bobbie") == 0);
127           break;
128         case 3:
129           assert (userid == 3 &&
130                   strcmp (username, "bob") == 0 &&
131                   strcmp (alias, "bobby") == 0);
132           break;
133         case 4:
134           assert (userid == 1 &&
135                   strcmp (username, "rich") == 0 &&
136                   strcmp (alias, "richard") == 0);
137           break;
138         case 5:
139           assert (userid == 1 &&
140                   strcmp (username, "rich") == 0 &&
141                   strcmp (alias, "richie") == 0);
142           break;
143         case 6:
144           assert (userid == 1 &&
145                   strcmp (username, "rich") == 0 &&
146                   strcmp (alias, "richy") == 0);
147           break;
148         case 7:
149           assert (userid == 3 &&
150                   strcmp (username, "bob") == 0 &&
151                   strcmp (alias, "robert") == 0);
152           break;
153         default:
154           abort ();
155         }
156
157       rownum++;
158     }
159
160   sth = st_prepare_cached
161     (dbh,
162      "select username from tdbi_users where age > 40 order by 1");
163   st_execute (sth);
164
165   st_bind (sth, 0, username, DBI_STRING);
166
167   rownum = 0;
168   while (st_fetch (sth))
169     {
170       switch (rownum)
171         {
172         case 0:
173           assert (strcmp (username, "anna") == 0);
174           break;
175         case 1:
176           assert (strcmp (username, "bob") == 0);
177           break;
178         default:
179           abort ();
180         }
181
182       rownum++;
183     }
184
185   /* Select out one row, no rows. */
186   sth = st_prepare_cached
187     (dbh,
188      "select userid from tdbi_users where username = ?", DBI_STRING);
189   st_execute (sth, "rich");
190
191   st_bind (sth, 0, userid, DBI_INT);
192
193   assert (st_fetch (sth) != 0);
194   assert (userid == 1);
195   assert (st_fetch (sth) == 0);
196   assert (userid == 1);         /* Hasn't splatted userid. */
197
198   st_execute (sth, "fred");
199
200   assert (st_fetch (sth) == 0);
201
202   /* Check the st_finish function does nothing bad. */
203   st_finish (sth);
204
205   /* Drop the tables. */
206   sth = st_prepare_cached
207     (dbh,
208      "drop table tdbi_aliases; drop table tdbi_users");
209   st_execute (sth);
210
211   /* Test timestamps and intervals.
212    * XXX Retrieval only tested/supported at present.
213    */
214   sth = st_prepare_cached
215     (dbh,
216      "create temporary table tdbi_times "
217      "  (ord int2 not null, ts timestamp, inv interval)");
218   st_execute (sth);
219
220   sth = st_prepare_cached
221     (dbh,
222      "insert into tdbi_times (ord, ts, inv) values (?, ?, ?)",
223      DBI_INT, DBI_STRING, DBI_STRING);
224   st_execute (sth, 0, "2002/11/09 01:02", 0);
225   st_execute (sth, 1, "2002/10/07 03:04:05", "1 year 1 day");
226   st_execute (sth, 2, "2002/09/04 06:07:08.999", "01:00");
227   st_execute (sth, 3, 0, "30 mins");
228   st_execute (sth, 4, 0, "1 year 2 months 6 days 8 hours 9 mins");
229
230   sth = st_prepare_cached
231     (dbh, "select ord, ts, inv from tdbi_times order by 1");
232   st_execute (sth);
233
234   st_bind (sth, 1, ts, DBI_TIMESTAMP);
235   st_bind (sth, 2, inv, DBI_INTERVAL);
236
237   assert (st_fetch (sth));
238   assert (!ts.is_null);
239   assert (ts.year == 2002 && ts.month == 11 && ts.day == 9 &&
240           ts.hour == 1 && ts.min == 2 && ts.sec == 0 &&
241           ts.microsecs == 0);
242   assert (inv.is_null);
243
244   assert (st_fetch (sth));
245   assert (!ts.is_null);
246   assert (ts.year == 2002 && ts.month == 10 && ts.day == 7 &&
247           ts.hour == 3 && ts.min == 4 && ts.sec == 5 &&
248           ts.microsecs == 0);
249   assert (!inv.is_null);
250   assert (inv.years == 1 && inv.months == 0 &&
251           inv.days == 1 && inv.hours == 0 && inv.mins == 0 &&
252           inv.secs == 0);
253
254   assert (st_fetch (sth));
255   assert (!ts.is_null);
256   assert (ts.year == 2002 && ts.month == 9 && ts.day == 4 &&
257           ts.hour == 6 && ts.min == 7 && ts.sec == 8 &&
258           ts.microsecs == 999);
259   assert (!inv.is_null);
260   assert (inv.years == 0 && inv.months == 0 &&
261           inv.days == 0 && inv.hours == 1 && inv.mins == 0 &&
262           inv.secs == 0);
263
264   assert (st_fetch (sth));
265   assert (ts.is_null);
266   assert (!inv.is_null);
267   assert (inv.years == 0 && inv.months == 0 &&
268           inv.days == 0 && inv.hours == 0 && inv.mins == 30 &&
269           inv.secs == 0);
270
271   assert (st_fetch (sth));
272   assert (ts.is_null);
273   assert (!inv.is_null);
274   assert (inv.years == 1 && inv.months == 2 &&
275           inv.days == 6 && inv.hours == 8 && inv.mins == 9 &&
276           inv.secs == 0);
277
278   /* Drop the table. */
279   sth = st_prepare_cached
280     (dbh,
281      "drop table tdbi_times");
282   st_execute (sth);
283
284   /* Try rolling back the database. */
285   db_rollback (dbh);
286 }
287
288 int
289 main ()
290 {
291   char *env = getenv ("TEST_DBI");
292
293   /* Skip the test unless the 'TEST_DBI' environment variable is set. */
294   if (!env || strcmp (env, "1") != 0)
295     {
296       fprintf (stderr,
297 "WARNING: DBI test skipped. If you want to run the DBI test, then you must\n"
298 "have:\n"
299 "  (a) A working PostgreSQL >= 7.1 database.\n"
300 "  (b) postgresql-devel packages installed (ie. libpq, header files).\n"
301 "  (c) PGHOST, etc., set up to provide access to a database where I can\n"
302 "      create temporary tables.\n"
303 "Set the TEST_DBI environment variable to 1 and run this test again.\n");
304
305       exit (0);
306     }
307
308   test_pool = new_pool ();
309   test_pth = new_pseudothread (test_pool, do_test, 0, "testing thread");
310   pth_start (test_pth);
311
312   while (pseudothread_count_threads () > 0)
313     reactor_invoke ();
314
315   exit (0);
316 }