2
0

dbd.c 14 KB

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