]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/apr-util/test/dbd.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / apr-util / test / dbd.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "apu.h"
18 #include "apr_pools.h"
19 #include "apr_dbd.h"
20
21 #include <stdio.h>
22
23 #define TEST(msg,func)                                  \
24     printf("======== %s ========\n", msg);              \
25     rv = func(pool, sql, driver);                       \
26     if (rv != 0) {                                      \
27         printf("Error in %s: rc=%d\n\n", msg, rv);      \
28     }                                                   \
29     else {                                              \
30         printf("%s test successful\n\n", msg);          \
31     }                                                   \
32     fflush(stdout);
33
34 static int create_table(apr_pool_t* pool, apr_dbd_t* handle,
35                         const apr_dbd_driver_t* driver)
36 {
37     int rv = 0;
38     int nrows;
39     const char *statement = "CREATE TABLE apr_dbd_test ("
40         "col1 varchar(40) not null,"
41         "col2 varchar(40),"
42         "col3 integer)" ;
43     rv = apr_dbd_query(driver, handle, &nrows, statement);
44     return rv;
45 }
46 static int drop_table(apr_pool_t* pool, apr_dbd_t* handle,
47                       const apr_dbd_driver_t* driver)
48 {
49     int rv = 0;
50     int nrows;
51     const char *statement = "DROP TABLE apr_dbd_test" ;
52     rv = apr_dbd_query(driver, handle, &nrows, statement);
53     return rv;
54 }
55 static int insert_rows(apr_pool_t* pool, apr_dbd_t* handle,
56                        const apr_dbd_driver_t* driver)
57 {
58     int i;
59     int rv = 0;
60     int nrows;
61     int nerrors = 0;
62     const char *statement =
63         "INSERT into apr_dbd_test (col1) values ('foo');"
64         "INSERT into apr_dbd_test values ('wibble', 'other', 5);"
65         "INSERT into apr_dbd_test values ('wibble', 'nothing', 5);"
66         "INSERT into apr_dbd_test values ('qwerty', 'foo', 0);"
67         "INSERT into apr_dbd_test values ('asdfgh', 'bar', 1);"
68     ;
69     rv = apr_dbd_query(driver, handle, &nrows, statement);
70     if (rv) {
71         const char* stmt[] = {
72             "INSERT into apr_dbd_test (col1) values ('foo');",
73             "INSERT into apr_dbd_test values ('wibble', 'other', 5);",
74             "INSERT into apr_dbd_test values ('wibble', 'nothing', 5);",
75             "INSERT into apr_dbd_test values ('qwerty', 'foo', 0);",
76             "INSERT into apr_dbd_test values ('asdfgh', 'bar', 1);",
77             NULL
78         };
79         printf("Compound insert failed; trying statements one-by-one\n") ;
80         for (i=0; stmt[i] != NULL; ++i) {
81             statement = stmt[i];
82             rv = apr_dbd_query(driver, handle, &nrows, statement);
83             if (rv) {
84                 nerrors++;
85             }
86         }
87         if (nerrors) {
88             printf("%d single inserts failed too.\n", nerrors) ;
89         }
90     }
91     return rv;
92 }
93 static int invalid_op(apr_pool_t* pool, apr_dbd_t* handle,
94                       const apr_dbd_driver_t* driver)
95 {
96     int rv = 0;
97     int nrows;
98     const char *statement = "INSERT into apr_dbd_test1 (col2) values ('foo')" ;
99     rv = apr_dbd_query(driver, handle, &nrows, statement);
100     printf("invalid op returned %d (should be nonzero).  Error msg follows\n", rv);
101     printf("'%s'\n", apr_dbd_error(driver, handle, rv));
102     statement = "INSERT into apr_dbd_test (col1, col2) values ('bar', 'foo')" ;
103     rv = apr_dbd_query(driver, handle, &nrows, statement);
104     printf("valid op returned %d (should be zero; error shouldn't affect subsequent ops)\n", rv);
105     return rv;
106 }
107 static int select_sequential(apr_pool_t* pool, apr_dbd_t* handle,
108                              const apr_dbd_driver_t* driver)
109 {
110     int rv = 0;
111     int i = 0;
112     int n;
113     const char* entry;
114     const char* statement = "SELECT * FROM apr_dbd_test ORDER BY col1, col2";
115     apr_dbd_results_t *res = NULL;
116     apr_dbd_row_t *row = NULL;
117     rv = apr_dbd_select(driver,pool,handle,&res,statement,0);
118     if (rv) {
119         printf("Select failed: %s", apr_dbd_error(driver, handle, rv));
120         return rv;
121     }
122     for (rv = apr_dbd_get_row(driver, pool, res, &row, -1);
123          rv == 0;
124          rv = apr_dbd_get_row(driver, pool, res, &row, -1)) {
125         printf("ROW %d: ", ++i) ;
126         for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
127             entry = apr_dbd_get_entry(driver, row, n);
128             if (entry == NULL) {
129                 printf("(null)  ") ;
130             }
131             else {
132                 printf("%s      ", entry);
133             }
134         }
135         fputs("\n", stdout);
136     }
137     return (rv == -1) ? 0 : 1;
138 }
139 static int select_random(apr_pool_t* pool, apr_dbd_t* handle,
140                          const apr_dbd_driver_t* driver)
141 {
142     int rv = 0;
143     int n;
144     const char* entry;
145     const char* statement = "SELECT * FROM apr_dbd_test ORDER BY col1, col2";
146     apr_dbd_results_t *res = NULL;
147     apr_dbd_row_t *row = NULL;
148     rv = apr_dbd_select(driver,pool,handle,&res,statement,1);
149     if (rv) {
150         printf("Select failed: %s", apr_dbd_error(driver, handle, rv));
151         return rv;
152     }
153     rv = apr_dbd_get_row(driver, pool, res, &row, 5) ;
154     if (rv) {
155         printf("get_row failed: %s", apr_dbd_error(driver, handle, rv));
156         return rv;
157     }
158     printf("ROW 5:      ");
159     for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
160         entry = apr_dbd_get_entry(driver, row, n);
161         if (entry == NULL) {
162             printf("(null)      ") ;
163         }
164         else {
165             printf("%s  ", entry);
166         }
167     }
168     fputs("\n", stdout);
169     rv = apr_dbd_get_row(driver, pool, res, &row, 1) ;
170     if (rv) {
171         printf("get_row failed: %s", apr_dbd_error(driver, handle, rv));
172         return rv;
173     }
174     printf("ROW 1:      ");
175     for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
176         entry = apr_dbd_get_entry(driver, row, n);
177         if (entry == NULL) {
178             printf("(null)      ") ;
179         }
180         else {
181             printf("%s  ", entry);
182         }
183     }
184     fputs("\n", stdout);
185     rv = apr_dbd_get_row(driver, pool, res, &row, 11) ;
186     if (rv != -1) {
187         printf("Oops!  get_row out of range but thinks it succeeded!\n%s\n",
188                 apr_dbd_error(driver, handle, rv));
189         return -1;
190     }
191     rv = 0;
192
193     return rv;
194 }
195 static int test_transactions(apr_pool_t* pool, apr_dbd_t* handle,
196                              const apr_dbd_driver_t* driver)
197 {
198     int rv = 0;
199     int nrows;
200     apr_dbd_transaction_t *trans = NULL;
201     const char* statement;
202
203     /* trans 1 - error out early */
204     printf("Transaction 1\n");
205     rv = apr_dbd_transaction_start(driver, pool, handle, &trans);
206     if (rv) {
207         printf("Start transaction failed!\n%s\n",
208                apr_dbd_error(driver, handle, rv));
209         return rv;
210     }
211     statement = "UPDATE apr_dbd_test SET col2 = 'failed'";
212     rv = apr_dbd_query(driver, handle, &nrows, statement);
213     if (rv) {
214         printf("Update failed: '%s'\n", apr_dbd_error(driver, handle, rv));
215         apr_dbd_transaction_end(driver, pool, trans);
216         return rv;
217     }
218     printf("%d rows updated\n", nrows);
219
220     statement = "INSERT INTO apr_dbd_test1 (col3) values (3)";
221     rv = apr_dbd_query(driver, handle, &nrows, statement);
222     if (!rv) {
223         printf("Oops, invalid op succeeded but shouldn't!\n");
224     }
225     statement = "INSERT INTO apr_dbd_test values ('zzz', 'aaa', 3)";
226     rv = apr_dbd_query(driver, handle, &nrows, statement);
227     printf("Valid insert returned %d.  Should be nonzero (fail) because transaction is bad\n", rv) ;
228
229     rv = apr_dbd_transaction_end(driver, pool, trans);
230     if (rv) {
231         printf("End transaction failed!\n%s\n",
232                apr_dbd_error(driver, handle, rv));
233         return rv;
234     }
235     printf("Transaction ended (should be rollback) - viewing table\n"
236            "A column of \"failed\" indicates transaction failed (no rollback)\n");
237     select_sequential(pool, handle, driver);
238
239     /* trans 2 - complete successfully */
240     printf("Transaction 2\n");
241     rv = apr_dbd_transaction_start(driver, pool, handle, &trans);
242     if (rv) {
243         printf("Start transaction failed!\n%s\n",
244                apr_dbd_error(driver, handle, rv));
245         return rv;
246     }
247     statement = "UPDATE apr_dbd_test SET col2 = 'success'";
248     rv = apr_dbd_query(driver, handle, &nrows, statement);
249     if (rv) {
250         printf("Update failed: '%s'\n", apr_dbd_error(driver, handle, rv));
251         apr_dbd_transaction_end(driver, pool, trans);
252         return rv;
253     }
254     printf("%d rows updated\n", nrows);
255     statement = "INSERT INTO apr_dbd_test values ('aaa', 'zzz', 3)";
256     rv = apr_dbd_query(driver, handle, &nrows, statement);
257     printf("Valid insert returned %d.  Should be zero (OK)\n", rv) ;
258     rv = apr_dbd_transaction_end(driver, pool, trans);
259     if (rv) {
260         printf("End transaction failed!\n%s\n",
261                apr_dbd_error(driver, handle, rv));
262         return rv;
263     }
264     printf("Transaction ended (should be commit) - viewing table\n");
265     select_sequential(pool, handle, driver);
266     return rv;
267 }
268 static int test_pselect(apr_pool_t* pool, apr_dbd_t* handle,
269                         const apr_dbd_driver_t* driver)
270 {
271     int rv = 0;
272     int i, n;
273     const char *query =
274         "SELECT * FROM apr_dbd_test WHERE col3 <= %s or col1 = 'bar'" ;
275     const char *label = "lowvalues";
276     apr_dbd_prepared_t *statement = NULL;
277     apr_dbd_results_t *res = NULL;
278     apr_dbd_row_t *row = NULL;
279     const char *entry = NULL;
280
281     rv = apr_dbd_prepare(driver, pool, handle, query, label, &statement);
282     if (rv) {
283         printf("Prepare statement failed!\n%s\n",
284                apr_dbd_error(driver, handle, rv));
285         return rv;
286     }
287     rv = apr_dbd_pvselect(driver, pool, handle, &res, statement, 0, "3", NULL);
288     if (rv) {
289         printf("Exec of prepared statement failed!\n%s\n",
290                apr_dbd_error(driver, handle, rv));
291         return rv;
292     }
293     i = 0;
294     printf("Selecting rows where col3 <= 3 and bar row where it's unset.\nShould show four rows.\n");
295     for (rv = apr_dbd_get_row(driver, pool, res, &row, -1);
296          rv == 0;
297          rv = apr_dbd_get_row(driver, pool, res, &row, -1)) {
298         printf("ROW %d: ", ++i) ;
299         for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
300             entry = apr_dbd_get_entry(driver, row, n);
301             if (entry == NULL) {
302                 printf("(null)  ") ;
303             }
304             else {
305                 printf("%s      ", entry);
306             }
307         }
308         fputs("\n", stdout);
309     }
310     return (rv == -1) ? 0 : 1;
311 }
312 static int test_pquery(apr_pool_t* pool, apr_dbd_t* handle,
313                        const apr_dbd_driver_t* driver)
314 {
315     int rv = 0;
316     const char *query = "INSERT INTO apr_dbd_test VALUES (%s, %s, %d)";
317     apr_dbd_prepared_t *statement = NULL;
318     const char *label = "testpquery";
319     int nrows;
320     apr_dbd_transaction_t *trans =0;
321
322     rv = apr_dbd_prepare(driver, pool, handle, query, label, &statement);
323     /* rv = apr_dbd_prepare(driver, pool, handle, query, NULL, &statement); */
324     if (rv) {
325         printf("Prepare statement failed!\n%s\n",
326                apr_dbd_error(driver, handle, rv));
327         return rv;
328     }
329     apr_dbd_transaction_start(driver, pool, handle, &trans);
330     rv = apr_dbd_pvquery(driver, pool, handle, &nrows, statement,
331                          "prepared", "insert", "2", NULL);
332     apr_dbd_transaction_end(driver, pool, trans);
333     if (rv) {
334         printf("Exec of prepared statement failed!\n%s\n",
335                apr_dbd_error(driver, handle, rv));
336         return rv;
337     }
338     printf("Showing table (should now contain row \"prepared insert 2\")\n");
339     select_sequential(pool, handle, driver);
340     return rv;
341 }
342 int main(int argc, char** argv)
343 {
344     const char *name;
345     const char *params;
346     apr_pool_t *pool = NULL;
347     apr_dbd_t *sql = NULL;
348     const apr_dbd_driver_t *driver = NULL;
349     int rv;
350
351     apr_initialize();
352     apr_pool_create(&pool, NULL);
353
354     if (argc >= 2 && argc <= 3) {
355         name = argv[1];
356         params = ( argc == 3 ) ? argv[2] : "";
357         apr_dbd_init(pool);
358         setbuf(stdout,NULL);
359         rv = apr_dbd_get_driver(pool, name, &driver);
360         switch (rv) {
361         case APR_SUCCESS:
362            printf("Loaded %s driver OK.\n", name);
363            break;
364         case APR_EDSOOPEN:
365            printf("Failed to load driver file apr_dbd_%s.so\n", name);
366            goto finish;
367         case APR_ESYMNOTFOUND:
368            printf("Failed to load driver apr_dbd_%s_driver.\n", name);
369            goto finish;
370         case APR_ENOTIMPL:
371            printf("No driver available for %s.\n", name);
372            goto finish;
373         default:        /* it's a bug if none of the above happen */
374            printf("Internal error loading %s.\n", name);
375            goto finish;
376         }
377         rv = apr_dbd_open(driver, pool, params, &sql);
378         switch (rv) {
379         case APR_SUCCESS:
380            printf("Opened %s[%s] OK\n", name, params);
381            break;
382         case APR_EGENERAL:
383            printf("Failed to open %s[%s]\n", name, params);
384            goto finish;
385         default:        /* it's a bug if none of the above happen */
386            printf("Internal error opening %s[%s]\n", name, params);
387            goto finish;
388         }
389         TEST("create table", create_table);
390         TEST("insert rows", insert_rows);
391         TEST("invalid op", invalid_op);
392         TEST("select random", select_random);
393         TEST("select sequential", select_sequential);
394         TEST("transactions", test_transactions);
395         TEST("prepared select", test_pselect);
396         TEST("prepared query", test_pquery);
397         TEST("drop table", drop_table);
398         apr_dbd_close(driver, sql);
399     }
400     else {
401         fprintf(stderr, "Usage: %s driver-name [params]\n", argv[0]);
402     }
403 finish:
404     apr_pool_destroy(pool);
405     apr_terminate();
406     return 0;
407 }