2
0

apr_dbd.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  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 <stdio.h>
  17. #include "apu.h"
  18. #include "apr_pools.h"
  19. #include "apr_dbd_internal.h"
  20. #include "apr_dbd.h"
  21. #include "apr_hash.h"
  22. #include "apr_thread_mutex.h"
  23. #include "apr_dso.h"
  24. #include "apr_strings.h"
  25. static apr_hash_t *drivers = NULL;
  26. #define CLEANUP_CAST (apr_status_t (*)(void*))
  27. /* Once the autofoo supports building it for dynamic load, we can use
  28. * #define APR_DSO_BUILD APR_HAS_DSO
  29. */
  30. #if APR_DSO_BUILD
  31. #if APR_HAS_THREADS
  32. static apr_thread_mutex_t* mutex = NULL;
  33. #endif
  34. #else
  35. #define DRIVER_LOAD(name,driver,pool) \
  36. { \
  37. extern const apr_dbd_driver_t driver; \
  38. apr_hash_set(drivers,name,APR_HASH_KEY_STRING,&driver); \
  39. if (driver.init) { \
  40. driver.init(pool); \
  41. } \
  42. }
  43. #endif
  44. static apr_status_t apr_dbd_term(void *ptr)
  45. {
  46. /* set drivers to NULL so init can work again */
  47. drivers = NULL;
  48. /* Everything else we need is handled by cleanups registered
  49. * when we created mutexes and loaded DSOs
  50. */
  51. return APR_SUCCESS;
  52. }
  53. APU_DECLARE(apr_status_t) apr_dbd_init(apr_pool_t *pool)
  54. {
  55. apr_status_t ret = APR_SUCCESS;
  56. if (drivers != NULL) {
  57. return APR_SUCCESS;
  58. }
  59. drivers = apr_hash_make(pool);
  60. apr_pool_cleanup_register(pool, NULL, apr_dbd_term,
  61. apr_pool_cleanup_null);
  62. #if APR_DSO_BUILD
  63. #if APR_HAS_THREADS
  64. ret = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, pool);
  65. /* This already registers a pool cleanup */
  66. #endif
  67. #else
  68. #if APU_HAVE_MYSQL
  69. DRIVER_LOAD("mysql", apr_dbd_mysql_driver, pool);
  70. #endif
  71. #if APU_HAVE_PGSQL
  72. DRIVER_LOAD("pgsql", apr_dbd_pgsql_driver, pool);
  73. #endif
  74. #if APU_HAVE_SQLITE3
  75. DRIVER_LOAD("sqlite3", apr_dbd_sqlite3_driver, pool);
  76. #endif
  77. #if APU_HAVE_SQLITE2
  78. DRIVER_LOAD("sqlite2", apr_dbd_sqlite2_driver, pool);
  79. #endif
  80. #if APU_HAVE_SOME_OTHER_BACKEND
  81. DRIVER_LOAD("firebird", apr_dbd_other_driver, pool);
  82. #endif
  83. #endif
  84. return ret;
  85. }
  86. APU_DECLARE(apr_status_t) apr_dbd_get_driver(apr_pool_t *pool, const char *name,
  87. const apr_dbd_driver_t **driver)
  88. {
  89. #if APR_DSO_BUILD
  90. char path[80];
  91. apr_dso_handle_t *dlhandle = NULL;
  92. #endif
  93. apr_status_t rv;
  94. *driver = apr_hash_get(drivers, name, APR_HASH_KEY_STRING);
  95. if (*driver) {
  96. return APR_SUCCESS;
  97. }
  98. #if APR_DSO_BUILD
  99. #if APR_HAS_THREADS
  100. rv = apr_thread_mutex_lock(mutex);
  101. if (rv != APR_SUCCESS) {
  102. goto unlock;
  103. }
  104. *driver = apr_hash_get(drivers, name, APR_HASH_KEY_STRING);
  105. if (*driver) {
  106. goto unlock;
  107. }
  108. #endif
  109. #ifdef WIN32
  110. sprintf(path, "apr_dbd_%s.dll", name);
  111. #else
  112. sprintf(path, "apr_dbd_%s.so", name);
  113. #endif
  114. rv = apr_dso_load(&dlhandle, path, pool);
  115. if (rv != APR_SUCCESS) { /* APR_EDSOOPEN */
  116. goto unlock;
  117. }
  118. sprintf(path, "apr_dbd_%s_driver", name);
  119. rv = apr_dso_sym((void*)driver, dlhandle, path);
  120. if (rv != APR_SUCCESS) { /* APR_ESYMNOTFOUND */
  121. apr_dso_unload(dlhandle);
  122. goto unlock;
  123. }
  124. if ((*driver)->init) {
  125. (*driver)->init(pool);
  126. }
  127. apr_hash_set(drivers, name, APR_HASH_KEY_STRING, *driver);
  128. unlock:
  129. #if APR_HAS_THREADS
  130. apr_thread_mutex_unlock(mutex);
  131. #endif
  132. #else /* APR_DSO_BUILD - so if it wasn't already loaded, it's NOTIMPL */
  133. rv = APR_ENOTIMPL;
  134. #endif
  135. return rv;
  136. }
  137. APU_DECLARE(apr_status_t) apr_dbd_open(const apr_dbd_driver_t *driver,
  138. apr_pool_t *pool, const char *params,
  139. apr_dbd_t **handle)
  140. {
  141. apr_status_t rv;
  142. *handle = driver->open(pool, params);
  143. if (*handle == NULL) {
  144. return APR_EGENERAL;
  145. }
  146. rv = apr_dbd_check_conn(driver, pool, *handle);
  147. if ((rv != APR_SUCCESS) && (rv != APR_ENOTIMPL)) {
  148. apr_dbd_close(driver, *handle);
  149. return APR_EGENERAL;
  150. }
  151. return APR_SUCCESS;
  152. }
  153. APU_DECLARE(int) apr_dbd_transaction_start(const apr_dbd_driver_t *driver,
  154. apr_pool_t *pool, apr_dbd_t *handle,
  155. apr_dbd_transaction_t **trans)
  156. {
  157. int ret = driver->start_transaction(pool, handle, trans);
  158. if (*trans) {
  159. apr_pool_cleanup_register(pool, *trans,
  160. CLEANUP_CAST driver->end_transaction,
  161. apr_pool_cleanup_null);
  162. }
  163. return ret;
  164. }
  165. APU_DECLARE(int) apr_dbd_transaction_end(const apr_dbd_driver_t *driver,
  166. apr_pool_t *pool,
  167. apr_dbd_transaction_t *trans)
  168. {
  169. apr_pool_cleanup_kill(pool, trans, CLEANUP_CAST driver->end_transaction);
  170. return driver->end_transaction(trans);
  171. }
  172. APU_DECLARE(apr_status_t) apr_dbd_close(const apr_dbd_driver_t *driver,
  173. apr_dbd_t *handle)
  174. {
  175. return driver->close(handle);
  176. }
  177. APU_DECLARE(const char*) apr_dbd_name(const apr_dbd_driver_t *driver)
  178. {
  179. return driver->name;
  180. }
  181. APU_DECLARE(void*) apr_dbd_native_handle(const apr_dbd_driver_t *driver,
  182. apr_dbd_t *handle)
  183. {
  184. return driver->native_handle(handle);
  185. }
  186. APU_DECLARE(int) apr_dbd_check_conn(const apr_dbd_driver_t *driver, apr_pool_t *pool,
  187. apr_dbd_t *handle)
  188. {
  189. return driver->check_conn(pool, handle);
  190. }
  191. APU_DECLARE(int) apr_dbd_set_dbname(const apr_dbd_driver_t *driver, apr_pool_t *pool,
  192. apr_dbd_t *handle, const char *name)
  193. {
  194. return driver->set_dbname(pool,handle,name);
  195. }
  196. APU_DECLARE(int) apr_dbd_query(const apr_dbd_driver_t *driver, apr_dbd_t *handle,
  197. int *nrows, const char *statement)
  198. {
  199. return driver->query(handle,nrows,statement);
  200. }
  201. APU_DECLARE(int) apr_dbd_select(const apr_dbd_driver_t *driver, apr_pool_t *pool,
  202. apr_dbd_t *handle, apr_dbd_results_t **res,
  203. const char *statement, int random)
  204. {
  205. return driver->select(pool,handle,res,statement,random);
  206. }
  207. APU_DECLARE(int) apr_dbd_num_cols(const apr_dbd_driver_t *driver,
  208. apr_dbd_results_t *res)
  209. {
  210. return driver->num_cols(res);
  211. }
  212. APU_DECLARE(int) apr_dbd_num_tuples(const apr_dbd_driver_t *driver,
  213. apr_dbd_results_t *res)
  214. {
  215. return driver->num_tuples(res);
  216. }
  217. APU_DECLARE(int) apr_dbd_get_row(const apr_dbd_driver_t *driver, apr_pool_t *pool,
  218. apr_dbd_results_t *res, apr_dbd_row_t **row,
  219. int rownum)
  220. {
  221. return driver->get_row(pool,res,row,rownum);
  222. }
  223. APU_DECLARE(const char*) apr_dbd_get_entry(const apr_dbd_driver_t *driver,
  224. apr_dbd_row_t *row, int col)
  225. {
  226. return driver->get_entry(row,col);
  227. }
  228. APU_DECLARE(const char*) apr_dbd_error(const apr_dbd_driver_t *driver,
  229. apr_dbd_t *handle, int errnum)
  230. {
  231. return driver->error(handle,errnum);
  232. }
  233. APU_DECLARE(const char*) apr_dbd_escape(const apr_dbd_driver_t *driver,
  234. apr_pool_t *pool, const char *string,
  235. apr_dbd_t *handle)
  236. {
  237. return driver->escape(pool,string,handle);
  238. }
  239. APU_DECLARE(int) apr_dbd_prepare(const apr_dbd_driver_t *driver, apr_pool_t *pool,
  240. apr_dbd_t *handle, const char *query,
  241. const char *label,
  242. apr_dbd_prepared_t **statement)
  243. {
  244. return driver->prepare(pool,handle,query,label,statement);
  245. }
  246. APU_DECLARE(int) apr_dbd_pquery(const apr_dbd_driver_t *driver, apr_pool_t *pool,
  247. apr_dbd_t *handle, int *nrows,
  248. apr_dbd_prepared_t *statement, int nargs,
  249. const char **args)
  250. {
  251. return driver->pquery(pool,handle,nrows,statement,nargs,args);
  252. }
  253. APU_DECLARE(int) apr_dbd_pselect(const apr_dbd_driver_t *driver, apr_pool_t *pool,
  254. apr_dbd_t *handle, apr_dbd_results_t **res,
  255. apr_dbd_prepared_t *statement, int random,
  256. int nargs, const char **args)
  257. {
  258. return driver->pselect(pool,handle,res,statement,random,nargs,args);
  259. }
  260. APU_DECLARE(int) apr_dbd_pvquery(const apr_dbd_driver_t *driver, apr_pool_t *pool,
  261. apr_dbd_t *handle, int *nrows,
  262. apr_dbd_prepared_t *statement,...)
  263. {
  264. int ret;
  265. va_list args;
  266. va_start(args, statement);
  267. ret = driver->pvquery(pool,handle,nrows,statement,args);
  268. va_end(args);
  269. return ret;
  270. }
  271. APU_DECLARE(int) apr_dbd_pvselect(const apr_dbd_driver_t *driver, apr_pool_t *pool,
  272. apr_dbd_t *handle, apr_dbd_results_t **res,
  273. apr_dbd_prepared_t *statement, int random,...)
  274. {
  275. int ret;
  276. va_list args;
  277. va_start(args, random);
  278. ret = driver->pvselect(pool,handle,res,statement,random,args);
  279. va_end(args);
  280. return ret;
  281. }