1251876Speter/* Licensed to the Apache Software Foundation (ASF) under one or more
2251876Speter * contributor license agreements.  See the NOTICE file distributed with
3251876Speter * this work for additional information regarding copyright ownership.
4251876Speter * The ASF licenses this file to You under the Apache License, Version 2.0
5251876Speter * (the "License"); you may not use this file except in compliance with
6251876Speter * the License.  You may obtain a copy of the License at
7251876Speter *
8251876Speter *     http://www.apache.org/licenses/LICENSE-2.0
9251876Speter *
10251876Speter * Unless required by applicable law or agreed to in writing, software
11251876Speter * distributed under the License is distributed on an "AS IS" BASIS,
12251876Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13251876Speter * See the License for the specific language governing permissions and
14251876Speter * limitations under the License.
15251876Speter */
16251876Speter
17251876Speter#include "apu.h"
18251876Speter#include "apr_pools.h"
19251876Speter#include "apr_dbd.h"
20251876Speter
21251876Speter#include <stdio.h>
22251876Speter
23251876Speter#define TEST(msg,func)					\
24251876Speter    printf("======== %s ========\n", msg);		\
25251876Speter    rv = func(pool, sql, driver);			\
26251876Speter    if (rv != 0) {					\
27251876Speter        printf("Error in %s: rc=%d\n\n", msg, rv);	\
28251876Speter    }							\
29251876Speter    else {						\
30251876Speter        printf("%s test successful\n\n", msg);		\
31251876Speter    }							\
32251876Speter    fflush(stdout);
33251876Speter
34251876Speterstatic int create_table(apr_pool_t* pool, apr_dbd_t* handle,
35251876Speter                        const apr_dbd_driver_t* driver)
36251876Speter{
37251876Speter    int rv = 0;
38251876Speter    int nrows;
39251876Speter    const char *statement = "CREATE TABLE apr_dbd_test ("
40251876Speter        "col1 varchar(40) not null,"
41251876Speter        "col2 varchar(40),"
42251876Speter        "col3 integer)" ;
43251876Speter    rv = apr_dbd_query(driver, handle, &nrows, statement);
44251876Speter    return rv;
45251876Speter}
46251876Speterstatic int drop_table(apr_pool_t* pool, apr_dbd_t* handle,
47251876Speter                      const apr_dbd_driver_t* driver)
48251876Speter{
49251876Speter    int rv = 0;
50251876Speter    int nrows;
51251876Speter    const char *statement = "DROP TABLE apr_dbd_test" ;
52251876Speter    rv = apr_dbd_query(driver, handle, &nrows, statement);
53251876Speter    return rv;
54251876Speter}
55251876Speterstatic int insert_rows(apr_pool_t* pool, apr_dbd_t* handle,
56251876Speter                       const apr_dbd_driver_t* driver)
57251876Speter{
58251876Speter    int i;
59251876Speter    int rv = 0;
60251876Speter    int nrows;
61251876Speter    int nerrors = 0;
62251876Speter    const char *statement =
63251876Speter        "INSERT into apr_dbd_test (col1) values ('foo');"
64251876Speter        "INSERT into apr_dbd_test values ('wibble', 'other', 5);"
65251876Speter        "INSERT into apr_dbd_test values ('wibble', 'nothing', 5);"
66251876Speter        "INSERT into apr_dbd_test values ('qwerty', 'foo', 0);"
67251876Speter        "INSERT into apr_dbd_test values ('asdfgh', 'bar', 1);"
68251876Speter    ;
69251876Speter    rv = apr_dbd_query(driver, handle, &nrows, statement);
70251876Speter    if (rv) {
71251876Speter        const char* stmt[] = {
72251876Speter            "INSERT into apr_dbd_test (col1) values ('foo');",
73251876Speter            "INSERT into apr_dbd_test values ('wibble', 'other', 5);",
74251876Speter            "INSERT into apr_dbd_test values ('wibble', 'nothing', 5);",
75251876Speter            "INSERT into apr_dbd_test values ('qwerty', 'foo', 0);",
76251876Speter            "INSERT into apr_dbd_test values ('asdfgh', 'bar', 1);",
77251876Speter            NULL
78251876Speter        };
79251876Speter        printf("Compound insert failed; trying statements one-by-one\n") ;
80251876Speter        for (i=0; stmt[i] != NULL; ++i) {
81251876Speter            statement = stmt[i];
82251876Speter            rv = apr_dbd_query(driver, handle, &nrows, statement);
83251876Speter            if (rv) {
84251876Speter                nerrors++;
85251876Speter            }
86251876Speter        }
87251876Speter        if (nerrors) {
88251876Speter            printf("%d single inserts failed too.\n", nerrors) ;
89251876Speter        }
90251876Speter    }
91251876Speter    return rv;
92251876Speter}
93251876Speterstatic int invalid_op(apr_pool_t* pool, apr_dbd_t* handle,
94251876Speter                      const apr_dbd_driver_t* driver)
95251876Speter{
96251876Speter    int rv = 0;
97251876Speter    int nrows;
98251876Speter    const char *statement = "INSERT into apr_dbd_test1 (col2) values ('foo')" ;
99251876Speter    rv = apr_dbd_query(driver, handle, &nrows, statement);
100251876Speter    printf("invalid op returned %d (should be nonzero).  Error msg follows\n", rv);
101251876Speter    printf("'%s'\n", apr_dbd_error(driver, handle, rv));
102251876Speter    statement = "INSERT into apr_dbd_test (col1, col2) values ('bar', 'foo')" ;
103251876Speter    rv = apr_dbd_query(driver, handle, &nrows, statement);
104251876Speter    printf("valid op returned %d (should be zero; error shouldn't affect subsequent ops)\n", rv);
105251876Speter    return rv;
106251876Speter}
107251876Speterstatic int select_sequential(apr_pool_t* pool, apr_dbd_t* handle,
108251876Speter                             const apr_dbd_driver_t* driver)
109251876Speter{
110251876Speter    int rv = 0;
111251876Speter    int i = 0;
112251876Speter    int n;
113251876Speter    const char* entry;
114251876Speter    const char* statement = "SELECT * FROM apr_dbd_test ORDER BY col1, col2";
115251876Speter    apr_dbd_results_t *res = NULL;
116251876Speter    apr_dbd_row_t *row = NULL;
117251876Speter    rv = apr_dbd_select(driver,pool,handle,&res,statement,0);
118251876Speter    if (rv) {
119251876Speter        printf("Select failed: %s", apr_dbd_error(driver, handle, rv));
120251876Speter        return rv;
121251876Speter    }
122251876Speter    for (rv = apr_dbd_get_row(driver, pool, res, &row, -1);
123251876Speter         rv == 0;
124251876Speter         rv = apr_dbd_get_row(driver, pool, res, &row, -1)) {
125251876Speter        printf("ROW %d:	", ++i) ;
126251876Speter        for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
127251876Speter            entry = apr_dbd_get_entry(driver, row, n);
128251876Speter            if (entry == NULL) {
129251876Speter                printf("(null)	") ;
130251876Speter            }
131251876Speter            else {
132251876Speter                printf("%s	", entry);
133251876Speter            }
134251876Speter        }
135251876Speter	fputs("\n", stdout);
136251876Speter    }
137251876Speter    return (rv == -1) ? 0 : 1;
138251876Speter}
139251876Speterstatic int select_random(apr_pool_t* pool, apr_dbd_t* handle,
140251876Speter                         const apr_dbd_driver_t* driver)
141251876Speter{
142251876Speter    int rv = 0;
143251876Speter    int n;
144251876Speter    const char* entry;
145251876Speter    const char* statement = "SELECT * FROM apr_dbd_test ORDER BY col1, col2";
146251876Speter    apr_dbd_results_t *res = NULL;
147251876Speter    apr_dbd_row_t *row = NULL;
148251876Speter    rv = apr_dbd_select(driver,pool,handle,&res,statement,1);
149251876Speter    if (rv) {
150251876Speter        printf("Select failed: %s", apr_dbd_error(driver, handle, rv));
151251876Speter        return rv;
152251876Speter    }
153251876Speter    rv = apr_dbd_get_row(driver, pool, res, &row, 5) ;
154251876Speter    if (rv) {
155251876Speter        printf("get_row failed: %s", apr_dbd_error(driver, handle, rv));
156251876Speter        return rv;
157251876Speter    }
158251876Speter    printf("ROW 5:	");
159251876Speter    for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
160251876Speter        entry = apr_dbd_get_entry(driver, row, n);
161251876Speter        if (entry == NULL) {
162251876Speter            printf("(null)	") ;
163251876Speter        }
164251876Speter        else {
165251876Speter            printf("%s	", entry);
166251876Speter        }
167251876Speter    }
168251876Speter    fputs("\n", stdout);
169251876Speter    rv = apr_dbd_get_row(driver, pool, res, &row, 1) ;
170251876Speter    if (rv) {
171251876Speter        printf("get_row failed: %s", apr_dbd_error(driver, handle, rv));
172251876Speter        return rv;
173251876Speter    }
174251876Speter    printf("ROW 1:	");
175251876Speter    for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
176251876Speter        entry = apr_dbd_get_entry(driver, row, n);
177251876Speter        if (entry == NULL) {
178251876Speter            printf("(null)	") ;
179251876Speter        }
180251876Speter        else {
181251876Speter            printf("%s	", entry);
182251876Speter        }
183251876Speter    }
184251876Speter    fputs("\n", stdout);
185251876Speter    rv = apr_dbd_get_row(driver, pool, res, &row, 11) ;
186251876Speter    if (rv != -1) {
187251876Speter        printf("Oops!  get_row out of range but thinks it succeeded!\n%s\n",
188251876Speter                apr_dbd_error(driver, handle, rv));
189251876Speter        return -1;
190251876Speter    }
191251876Speter    rv = 0;
192251876Speter
193251876Speter    return rv;
194251876Speter}
195251876Speterstatic int test_transactions(apr_pool_t* pool, apr_dbd_t* handle,
196251876Speter                             const apr_dbd_driver_t* driver)
197251876Speter{
198251876Speter    int rv = 0;
199251876Speter    int nrows;
200251876Speter    apr_dbd_transaction_t *trans = NULL;
201251876Speter    const char* statement;
202251876Speter
203251876Speter    /* trans 1 - error out early */
204251876Speter    printf("Transaction 1\n");
205251876Speter    rv = apr_dbd_transaction_start(driver, pool, handle, &trans);
206251876Speter    if (rv) {
207251876Speter        printf("Start transaction failed!\n%s\n",
208251876Speter               apr_dbd_error(driver, handle, rv));
209251876Speter        return rv;
210251876Speter    }
211251876Speter    statement = "UPDATE apr_dbd_test SET col2 = 'failed'";
212251876Speter    rv = apr_dbd_query(driver, handle, &nrows, statement);
213251876Speter    if (rv) {
214251876Speter        printf("Update failed: '%s'\n", apr_dbd_error(driver, handle, rv));
215251876Speter        apr_dbd_transaction_end(driver, pool, trans);
216251876Speter        return rv;
217251876Speter    }
218251876Speter    printf("%d rows updated\n", nrows);
219251876Speter
220251876Speter    statement = "INSERT INTO apr_dbd_test1 (col3) values (3)";
221251876Speter    rv = apr_dbd_query(driver, handle, &nrows, statement);
222251876Speter    if (!rv) {
223251876Speter        printf("Oops, invalid op succeeded but shouldn't!\n");
224251876Speter    }
225251876Speter    statement = "INSERT INTO apr_dbd_test values ('zzz', 'aaa', 3)";
226251876Speter    rv = apr_dbd_query(driver, handle, &nrows, statement);
227251876Speter    printf("Valid insert returned %d.  Should be nonzero (fail) because transaction is bad\n", rv) ;
228251876Speter
229251876Speter    rv = apr_dbd_transaction_end(driver, pool, trans);
230251876Speter    if (rv) {
231251876Speter        printf("End transaction failed!\n%s\n",
232251876Speter               apr_dbd_error(driver, handle, rv));
233251876Speter        return rv;
234251876Speter    }
235251876Speter    printf("Transaction ended (should be rollback) - viewing table\n"
236251876Speter           "A column of \"failed\" indicates transaction failed (no rollback)\n");
237251876Speter    select_sequential(pool, handle, driver);
238251876Speter
239251876Speter    /* trans 2 - complete successfully */
240251876Speter    printf("Transaction 2\n");
241251876Speter    rv = apr_dbd_transaction_start(driver, pool, handle, &trans);
242251876Speter    if (rv) {
243251876Speter        printf("Start transaction failed!\n%s\n",
244251876Speter               apr_dbd_error(driver, handle, rv));
245251876Speter        return rv;
246251876Speter    }
247251876Speter    statement = "UPDATE apr_dbd_test SET col2 = 'success'";
248251876Speter    rv = apr_dbd_query(driver, handle, &nrows, statement);
249251876Speter    if (rv) {
250251876Speter        printf("Update failed: '%s'\n", apr_dbd_error(driver, handle, rv));
251251876Speter        apr_dbd_transaction_end(driver, pool, trans);
252251876Speter        return rv;
253251876Speter    }
254251876Speter    printf("%d rows updated\n", nrows);
255251876Speter    statement = "INSERT INTO apr_dbd_test values ('aaa', 'zzz', 3)";
256251876Speter    rv = apr_dbd_query(driver, handle, &nrows, statement);
257251876Speter    printf("Valid insert returned %d.  Should be zero (OK)\n", rv) ;
258251876Speter    rv = apr_dbd_transaction_end(driver, pool, trans);
259251876Speter    if (rv) {
260251876Speter        printf("End transaction failed!\n%s\n",
261251876Speter               apr_dbd_error(driver, handle, rv));
262251876Speter        return rv;
263251876Speter    }
264251876Speter    printf("Transaction ended (should be commit) - viewing table\n");
265251876Speter    select_sequential(pool, handle, driver);
266251876Speter    return rv;
267251876Speter}
268251876Speterstatic int test_pselect(apr_pool_t* pool, apr_dbd_t* handle,
269251876Speter                        const apr_dbd_driver_t* driver)
270251876Speter{
271251876Speter    int rv = 0;
272251876Speter    int i, n;
273251876Speter    const char *query =
274251876Speter        "SELECT * FROM apr_dbd_test WHERE col3 <= %s or col1 = 'bar'" ;
275251876Speter    const char *label = "lowvalues";
276251876Speter    apr_dbd_prepared_t *statement = NULL;
277251876Speter    apr_dbd_results_t *res = NULL;
278251876Speter    apr_dbd_row_t *row = NULL;
279251876Speter    const char *entry = NULL;
280251876Speter
281251876Speter    rv = apr_dbd_prepare(driver, pool, handle, query, label, &statement);
282251876Speter    if (rv) {
283251876Speter        printf("Prepare statement failed!\n%s\n",
284251876Speter               apr_dbd_error(driver, handle, rv));
285251876Speter        return rv;
286251876Speter    }
287251876Speter    rv = apr_dbd_pvselect(driver, pool, handle, &res, statement, 0, "3", NULL);
288251876Speter    if (rv) {
289251876Speter        printf("Exec of prepared statement failed!\n%s\n",
290251876Speter               apr_dbd_error(driver, handle, rv));
291251876Speter        return rv;
292251876Speter    }
293251876Speter    i = 0;
294251876Speter    printf("Selecting rows where col3 <= 3 and bar row where it's unset.\nShould show four rows.\n");
295251876Speter    for (rv = apr_dbd_get_row(driver, pool, res, &row, -1);
296251876Speter         rv == 0;
297251876Speter         rv = apr_dbd_get_row(driver, pool, res, &row, -1)) {
298251876Speter        printf("ROW %d:	", ++i) ;
299251876Speter        for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
300251876Speter            entry = apr_dbd_get_entry(driver, row, n);
301251876Speter            if (entry == NULL) {
302251876Speter                printf("(null)	") ;
303251876Speter            }
304251876Speter            else {
305251876Speter                printf("%s	", entry);
306251876Speter            }
307251876Speter        }
308251876Speter	fputs("\n", stdout);
309251876Speter    }
310251876Speter    return (rv == -1) ? 0 : 1;
311251876Speter}
312251876Speterstatic int test_pquery(apr_pool_t* pool, apr_dbd_t* handle,
313251876Speter                       const apr_dbd_driver_t* driver)
314251876Speter{
315251876Speter    int rv = 0;
316251876Speter    const char *query = "INSERT INTO apr_dbd_test VALUES (%s, %s, %d)";
317251876Speter    apr_dbd_prepared_t *statement = NULL;
318251876Speter    const char *label = "testpquery";
319251876Speter    int nrows;
320251876Speter    apr_dbd_transaction_t *trans =0;
321251876Speter
322251876Speter    rv = apr_dbd_prepare(driver, pool, handle, query, label, &statement);
323251876Speter    /* rv = apr_dbd_prepare(driver, pool, handle, query, NULL, &statement); */
324251876Speter    if (rv) {
325251876Speter        printf("Prepare statement failed!\n%s\n",
326251876Speter               apr_dbd_error(driver, handle, rv));
327251876Speter        return rv;
328251876Speter    }
329251876Speter    apr_dbd_transaction_start(driver, pool, handle, &trans);
330251876Speter    rv = apr_dbd_pvquery(driver, pool, handle, &nrows, statement,
331251876Speter                         "prepared", "insert", "2", NULL);
332251876Speter    apr_dbd_transaction_end(driver, pool, trans);
333251876Speter    if (rv) {
334251876Speter        printf("Exec of prepared statement failed!\n%s\n",
335251876Speter               apr_dbd_error(driver, handle, rv));
336251876Speter        return rv;
337251876Speter    }
338251876Speter    printf("Showing table (should now contain row \"prepared insert 2\")\n");
339251876Speter    select_sequential(pool, handle, driver);
340251876Speter    return rv;
341251876Speter}
342251876Speterint main(int argc, char** argv)
343251876Speter{
344251876Speter    const char *name;
345251876Speter    const char *params;
346251876Speter    apr_pool_t *pool = NULL;
347251876Speter    apr_dbd_t *sql = NULL;
348251876Speter    const apr_dbd_driver_t *driver = NULL;
349251876Speter    int rv;
350251876Speter
351251876Speter    apr_initialize();
352251876Speter    apr_pool_create(&pool, NULL);
353251876Speter
354251876Speter    if (argc >= 2 && argc <= 3) {
355251876Speter        name = argv[1];
356251876Speter        params = ( argc == 3 ) ? argv[2] : "";
357251876Speter        apr_dbd_init(pool);
358251876Speter        setbuf(stdout,NULL);
359251876Speter        rv = apr_dbd_get_driver(pool, name, &driver);
360251876Speter        switch (rv) {
361251876Speter        case APR_SUCCESS:
362251876Speter           printf("Loaded %s driver OK.\n", name);
363251876Speter           break;
364251876Speter        case APR_EDSOOPEN:
365251876Speter           printf("Failed to load driver file apr_dbd_%s.so\n", name);
366251876Speter           goto finish;
367251876Speter        case APR_ESYMNOTFOUND:
368251876Speter           printf("Failed to load driver apr_dbd_%s_driver.\n", name);
369251876Speter           goto finish;
370251876Speter        case APR_ENOTIMPL:
371251876Speter           printf("No driver available for %s.\n", name);
372251876Speter           goto finish;
373251876Speter        default:        /* it's a bug if none of the above happen */
374251876Speter           printf("Internal error loading %s.\n", name);
375251876Speter           goto finish;
376251876Speter        }
377251876Speter        rv = apr_dbd_open(driver, pool, params, &sql);
378251876Speter        switch (rv) {
379251876Speter        case APR_SUCCESS:
380251876Speter           printf("Opened %s[%s] OK\n", name, params);
381251876Speter           break;
382251876Speter        case APR_EGENERAL:
383251876Speter           printf("Failed to open %s[%s]\n", name, params);
384251876Speter           goto finish;
385251876Speter        default:        /* it's a bug if none of the above happen */
386251876Speter           printf("Internal error opening %s[%s]\n", name, params);
387251876Speter           goto finish;
388251876Speter        }
389251876Speter        TEST("create table", create_table);
390251876Speter        TEST("insert rows", insert_rows);
391251876Speter        TEST("invalid op", invalid_op);
392251876Speter        TEST("select random", select_random);
393251876Speter        TEST("select sequential", select_sequential);
394251876Speter        TEST("transactions", test_transactions);
395251876Speter        TEST("prepared select", test_pselect);
396251876Speter        TEST("prepared query", test_pquery);
397251876Speter        TEST("drop table", drop_table);
398251876Speter        apr_dbd_close(driver, sql);
399251876Speter    }
400251876Speter    else {
401251876Speter        fprintf(stderr, "Usage: %s driver-name [params]\n", argv[0]);
402251876Speter    }
403251876Speterfinish:
404251876Speter    apr_pool_destroy(pool);
405251876Speter    apr_terminate();
406251876Speter    return 0;
407251876Speter}
408