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