You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3799 lines
104 KiB

14 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
26 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
26 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
26 years ago
26 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
20 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
23 years ago
23 years ago
20 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
26 years ago
19 years ago
19 years ago
19 years ago
19 years ago
23 years ago
23 years ago
23 years ago
23 years ago
23 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
26 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
26 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
26 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
26 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
24 years ago
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 5 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2012 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Authors: Stig Sther Bakken <ssb@php.net> |
  16. | Andreas Karajannis <Andreas.Karajannis@gmd.de> |
  17. | Frank M. Kromann <frank@kromann.info> Support for DB/2 CLI |
  18. | Kevin N. Shallow <kshallow@tampabay.rr.com> Birdstep Support|
  19. | Daniel R. Kalowsky <kalowsky@php.net> |
  20. +----------------------------------------------------------------------+
  21. */
  22. /* $Id$ */
  23. #ifdef HAVE_CONFIG_H
  24. #include "config.h"
  25. #endif
  26. #include "php.h"
  27. #include "php_globals.h"
  28. #include "ext/standard/info.h"
  29. #include "ext/standard/php_string.h"
  30. #include "ext/standard/php_standard.h"
  31. #include "php_odbc.h"
  32. #include "php_odbc_includes.h"
  33. #include "php_globals.h"
  34. #if HAVE_UODBC
  35. #include <fcntl.h>
  36. #include "ext/standard/head.h"
  37. #include "php_ini.h"
  38. #ifdef PHP_WIN32
  39. #include <winsock2.h>
  40. #define ODBC_TYPE "Win32"
  41. #define PHP_ODBC_TYPE ODBC_TYPE
  42. #endif
  43. /*
  44. * not defined elsewhere
  45. */
  46. #ifndef TRUE
  47. #define TRUE 1
  48. #define FALSE 0
  49. #endif
  50. void odbc_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent);
  51. static int le_result, le_conn, le_pconn;
  52. #define SAFE_SQL_NTS(n) ((SQLSMALLINT) ((n)?(SQL_NTS):0))
  53. /* {{{ arginfo */
  54. ZEND_BEGIN_ARG_INFO(arginfo_odbc_close_all, 0)
  55. ZEND_END_ARG_INFO()
  56. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_binmode, 0, 0, 2)
  57. ZEND_ARG_INFO(0, result_id)
  58. ZEND_ARG_INFO(0, mode)
  59. ZEND_END_ARG_INFO()
  60. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_longreadlen, 0, 0, 2)
  61. ZEND_ARG_INFO(0, result_id)
  62. ZEND_ARG_INFO(0, length)
  63. ZEND_END_ARG_INFO()
  64. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_prepare, 0, 0, 2)
  65. ZEND_ARG_INFO(0, connection_id)
  66. ZEND_ARG_INFO(0, query)
  67. ZEND_END_ARG_INFO()
  68. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_execute, 0, 0, 1)
  69. ZEND_ARG_INFO(0, result_id)
  70. ZEND_ARG_INFO(0, parameters_array)
  71. ZEND_END_ARG_INFO()
  72. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_cursor, 0, 0, 1)
  73. ZEND_ARG_INFO(0, result_id)
  74. ZEND_END_ARG_INFO()
  75. #ifdef HAVE_SQLDATASOURCES
  76. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_data_source, 0, 0, 2)
  77. ZEND_ARG_INFO(0, connection_id)
  78. ZEND_ARG_INFO(0, fetch_type)
  79. ZEND_END_ARG_INFO()
  80. #endif
  81. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_exec, 0, 0, 2)
  82. ZEND_ARG_INFO(0, connection_id)
  83. ZEND_ARG_INFO(0, query)
  84. ZEND_ARG_INFO(0, flags)
  85. ZEND_END_ARG_INFO()
  86. #ifdef PHP_ODBC_HAVE_FETCH_HASH
  87. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_fetch_object, 0, 0, 1)
  88. ZEND_ARG_INFO(0, result)
  89. ZEND_ARG_INFO(0, rownumber)
  90. ZEND_END_ARG_INFO()
  91. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_fetch_array, 0, 0, 1)
  92. ZEND_ARG_INFO(0, result)
  93. ZEND_ARG_INFO(0, rownumber)
  94. ZEND_END_ARG_INFO()
  95. #endif
  96. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_fetch_into, 0, 0, 2)
  97. ZEND_ARG_INFO(0, result_id)
  98. ZEND_ARG_INFO(1, result_array)
  99. ZEND_ARG_INFO(0, rownumber)
  100. ZEND_END_ARG_INFO()
  101. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_fetch_row, 0, 0, 1)
  102. ZEND_ARG_INFO(0, result_id)
  103. ZEND_ARG_INFO(0, row_number)
  104. ZEND_END_ARG_INFO()
  105. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_result, 0, 0, 2)
  106. ZEND_ARG_INFO(0, result_id)
  107. ZEND_ARG_INFO(0, field)
  108. ZEND_END_ARG_INFO()
  109. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_result_all, 0, 0, 1)
  110. ZEND_ARG_INFO(0, result_id)
  111. ZEND_ARG_INFO(0, format)
  112. ZEND_END_ARG_INFO()
  113. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_free_result, 0, 0, 1)
  114. ZEND_ARG_INFO(0, result_id)
  115. ZEND_END_ARG_INFO()
  116. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_connect, 0, 0, 3)
  117. ZEND_ARG_INFO(0, dsn)
  118. ZEND_ARG_INFO(0, user)
  119. ZEND_ARG_INFO(0, password)
  120. ZEND_ARG_INFO(0, cursor_option)
  121. ZEND_END_ARG_INFO()
  122. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_pconnect, 0, 0, 3)
  123. ZEND_ARG_INFO(0, dsn)
  124. ZEND_ARG_INFO(0, user)
  125. ZEND_ARG_INFO(0, password)
  126. ZEND_ARG_INFO(0, cursor_option)
  127. ZEND_END_ARG_INFO()
  128. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_close, 0, 0, 1)
  129. ZEND_ARG_INFO(0, connection_id)
  130. ZEND_END_ARG_INFO()
  131. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_num_rows, 0, 0, 1)
  132. ZEND_ARG_INFO(0, result_id)
  133. ZEND_END_ARG_INFO()
  134. #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30)
  135. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_next_result, 0, 0, 1)
  136. ZEND_ARG_INFO(0, result_id)
  137. ZEND_END_ARG_INFO()
  138. #endif
  139. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_num_fields, 0, 0, 1)
  140. ZEND_ARG_INFO(0, result_id)
  141. ZEND_END_ARG_INFO()
  142. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_field_name, 0, 0, 2)
  143. ZEND_ARG_INFO(0, result_id)
  144. ZEND_ARG_INFO(0, field_number)
  145. ZEND_END_ARG_INFO()
  146. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_field_type, 0, 0, 2)
  147. ZEND_ARG_INFO(0, result_id)
  148. ZEND_ARG_INFO(0, field_number)
  149. ZEND_END_ARG_INFO()
  150. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_field_len, 0, 0, 2)
  151. ZEND_ARG_INFO(0, result_id)
  152. ZEND_ARG_INFO(0, field_number)
  153. ZEND_END_ARG_INFO()
  154. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_field_scale, 0, 0, 2)
  155. ZEND_ARG_INFO(0, result_id)
  156. ZEND_ARG_INFO(0, field_number)
  157. ZEND_END_ARG_INFO()
  158. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_field_num, 0, 0, 2)
  159. ZEND_ARG_INFO(0, result_id)
  160. ZEND_ARG_INFO(0, field_name)
  161. ZEND_END_ARG_INFO()
  162. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_autocommit, 0, 0, 1)
  163. ZEND_ARG_INFO(0, connection_id)
  164. ZEND_ARG_INFO(0, onoff)
  165. ZEND_END_ARG_INFO()
  166. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_commit, 0, 0, 1)
  167. ZEND_ARG_INFO(0, connection_id)
  168. ZEND_END_ARG_INFO()
  169. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_rollback, 0, 0, 1)
  170. ZEND_ARG_INFO(0, connection_id)
  171. ZEND_END_ARG_INFO()
  172. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_error, 0, 0, 0)
  173. ZEND_ARG_INFO(0, connection_id)
  174. ZEND_END_ARG_INFO()
  175. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_errormsg, 0, 0, 0)
  176. ZEND_ARG_INFO(0, connection_id)
  177. ZEND_END_ARG_INFO()
  178. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_setoption, 0, 0, 4)
  179. ZEND_ARG_INFO(0, conn_id)
  180. ZEND_ARG_INFO(0, which)
  181. ZEND_ARG_INFO(0, option)
  182. ZEND_ARG_INFO(0, value)
  183. ZEND_END_ARG_INFO()
  184. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_tables, 0, 0, 1)
  185. ZEND_ARG_INFO(0, connection_id)
  186. ZEND_ARG_INFO(0, qualifier)
  187. ZEND_ARG_INFO(0, owner)
  188. ZEND_ARG_INFO(0, name)
  189. ZEND_ARG_INFO(0, table_types)
  190. ZEND_END_ARG_INFO()
  191. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_columns, 0, 0, 1)
  192. ZEND_ARG_INFO(0, connection_id)
  193. ZEND_ARG_INFO(0, qualifier)
  194. ZEND_ARG_INFO(0, owner)
  195. ZEND_ARG_INFO(0, table_name)
  196. ZEND_ARG_INFO(0, column_name)
  197. ZEND_END_ARG_INFO()
  198. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_gettypeinfo, 0, 0, 1)
  199. ZEND_ARG_INFO(0, connection_id)
  200. ZEND_ARG_INFO(0, data_type)
  201. ZEND_END_ARG_INFO()
  202. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_primarykeys, 0, 0, 4)
  203. ZEND_ARG_INFO(0, connection_id)
  204. ZEND_ARG_INFO(0, qualifier)
  205. ZEND_ARG_INFO(0, owner)
  206. ZEND_ARG_INFO(0, table)
  207. ZEND_END_ARG_INFO()
  208. #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35)
  209. #if !defined(HAVE_BIRDSTEP)
  210. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_procedurecolumns, 0, 0, 1)
  211. ZEND_ARG_INFO(0, connection_id)
  212. ZEND_ARG_INFO(0, qualifier)
  213. ZEND_ARG_INFO(0, owner)
  214. ZEND_ARG_INFO(0, proc)
  215. ZEND_ARG_INFO(0, column)
  216. ZEND_END_ARG_INFO()
  217. #endif
  218. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_procedures, 0, 0, 1)
  219. ZEND_ARG_INFO(0, connection_id)
  220. ZEND_ARG_INFO(0, qualifier)
  221. ZEND_ARG_INFO(0, owner)
  222. ZEND_ARG_INFO(0, name)
  223. ZEND_END_ARG_INFO()
  224. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_foreignkeys, 0, 0, 7)
  225. ZEND_ARG_INFO(0, connection_id)
  226. ZEND_ARG_INFO(0, pk_qualifier)
  227. ZEND_ARG_INFO(0, pk_owner)
  228. ZEND_ARG_INFO(0, pk_table)
  229. ZEND_ARG_INFO(0, fk_qualifier)
  230. ZEND_ARG_INFO(0, fk_owner)
  231. ZEND_ARG_INFO(0, fk_table)
  232. ZEND_END_ARG_INFO()
  233. #endif
  234. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_specialcolumns, 0, 0, 7)
  235. ZEND_ARG_INFO(0, connection_id)
  236. ZEND_ARG_INFO(0, type)
  237. ZEND_ARG_INFO(0, qualifier)
  238. ZEND_ARG_INFO(0, owner)
  239. ZEND_ARG_INFO(0, table)
  240. ZEND_ARG_INFO(0, scope)
  241. ZEND_ARG_INFO(0, nullable)
  242. ZEND_END_ARG_INFO()
  243. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_statistics, 0, 0, 6)
  244. ZEND_ARG_INFO(0, connection_id)
  245. ZEND_ARG_INFO(0, qualifier)
  246. ZEND_ARG_INFO(0, owner)
  247. ZEND_ARG_INFO(0, name)
  248. ZEND_ARG_INFO(0, unique)
  249. ZEND_ARG_INFO(0, accuracy)
  250. ZEND_END_ARG_INFO()
  251. #if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) &&!defined(HAVE_SOLID_35) && !defined(HAVE_BIRDSTEP)
  252. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_tableprivileges, 0, 0, 4)
  253. ZEND_ARG_INFO(0, connection_id)
  254. ZEND_ARG_INFO(0, qualifier)
  255. ZEND_ARG_INFO(0, owner)
  256. ZEND_ARG_INFO(0, name)
  257. ZEND_END_ARG_INFO()
  258. ZEND_BEGIN_ARG_INFO_EX(arginfo_odbc_columnprivileges, 0, 0, 5)
  259. ZEND_ARG_INFO(0, connection_id)
  260. ZEND_ARG_INFO(0, catalog)
  261. ZEND_ARG_INFO(0, schema)
  262. ZEND_ARG_INFO(0, table)
  263. ZEND_ARG_INFO(0, column)
  264. ZEND_END_ARG_INFO()
  265. #endif
  266. /* }}} */
  267. /* {{{ odbc_functions[]
  268. */
  269. const zend_function_entry odbc_functions[] = {
  270. PHP_FE(odbc_autocommit, arginfo_odbc_autocommit)
  271. PHP_FE(odbc_binmode, arginfo_odbc_binmode)
  272. PHP_FE(odbc_close, arginfo_odbc_close)
  273. PHP_FE(odbc_close_all, arginfo_odbc_close_all)
  274. PHP_FE(odbc_columns, arginfo_odbc_columns)
  275. PHP_FE(odbc_commit, arginfo_odbc_commit)
  276. PHP_FE(odbc_connect, arginfo_odbc_connect)
  277. PHP_FE(odbc_cursor, arginfo_odbc_cursor)
  278. #ifdef HAVE_SQLDATASOURCES
  279. PHP_FE(odbc_data_source, arginfo_odbc_data_source)
  280. #endif
  281. PHP_FE(odbc_execute, arginfo_odbc_execute)
  282. PHP_FE(odbc_error, arginfo_odbc_error)
  283. PHP_FE(odbc_errormsg, arginfo_odbc_errormsg)
  284. PHP_FE(odbc_exec, arginfo_odbc_exec)
  285. #ifdef PHP_ODBC_HAVE_FETCH_HASH
  286. PHP_FE(odbc_fetch_array, arginfo_odbc_fetch_array)
  287. PHP_FE(odbc_fetch_object, arginfo_odbc_fetch_object)
  288. #endif
  289. PHP_FE(odbc_fetch_row, arginfo_odbc_fetch_row)
  290. PHP_FE(odbc_fetch_into, arginfo_odbc_fetch_into)
  291. PHP_FE(odbc_field_len, arginfo_odbc_field_len)
  292. PHP_FE(odbc_field_scale, arginfo_odbc_field_scale)
  293. PHP_FE(odbc_field_name, arginfo_odbc_field_name)
  294. PHP_FE(odbc_field_type, arginfo_odbc_field_type)
  295. PHP_FE(odbc_field_num, arginfo_odbc_field_num)
  296. PHP_FE(odbc_free_result, arginfo_odbc_free_result)
  297. PHP_FE(odbc_gettypeinfo, arginfo_odbc_gettypeinfo)
  298. PHP_FE(odbc_longreadlen, arginfo_odbc_longreadlen)
  299. #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30)
  300. PHP_FE(odbc_next_result, arginfo_odbc_next_result)
  301. #endif
  302. PHP_FE(odbc_num_fields, arginfo_odbc_num_fields)
  303. PHP_FE(odbc_num_rows, arginfo_odbc_num_rows)
  304. PHP_FE(odbc_pconnect, arginfo_odbc_pconnect)
  305. PHP_FE(odbc_prepare, arginfo_odbc_prepare)
  306. PHP_FE(odbc_result, arginfo_odbc_result)
  307. PHP_FE(odbc_result_all, arginfo_odbc_result_all)
  308. PHP_FE(odbc_rollback, arginfo_odbc_rollback)
  309. PHP_FE(odbc_setoption, arginfo_odbc_setoption)
  310. PHP_FE(odbc_specialcolumns, arginfo_odbc_specialcolumns)
  311. PHP_FE(odbc_statistics, arginfo_odbc_statistics)
  312. PHP_FE(odbc_tables, arginfo_odbc_tables)
  313. PHP_FE(odbc_primarykeys, arginfo_odbc_primarykeys)
  314. #if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) &&!defined(HAVE_SOLID_35) && !defined(HAVE_BIRDSTEP) /* not supported now */
  315. PHP_FE(odbc_columnprivileges, arginfo_odbc_columnprivileges)
  316. PHP_FE(odbc_tableprivileges, arginfo_odbc_tableprivileges)
  317. #endif
  318. #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) /* not supported */
  319. PHP_FE(odbc_foreignkeys, arginfo_odbc_foreignkeys)
  320. PHP_FE(odbc_procedures, arginfo_odbc_procedures)
  321. #if !defined(HAVE_BIRDSTEP)
  322. PHP_FE(odbc_procedurecolumns, arginfo_odbc_procedurecolumns)
  323. #endif
  324. #endif
  325. PHP_FALIAS(odbc_do, odbc_exec, arginfo_odbc_exec)
  326. PHP_FALIAS(odbc_field_precision, odbc_field_len, arginfo_odbc_field_len)
  327. PHP_FE_END
  328. };
  329. /* }}} */
  330. ZEND_DECLARE_MODULE_GLOBALS(odbc);
  331. static PHP_GINIT_FUNCTION(odbc);
  332. /* {{{ odbc_module_entry
  333. */
  334. zend_module_entry odbc_module_entry = {
  335. STANDARD_MODULE_HEADER,
  336. "odbc",
  337. odbc_functions,
  338. PHP_MINIT(odbc),
  339. PHP_MSHUTDOWN(odbc),
  340. PHP_RINIT(odbc),
  341. PHP_RSHUTDOWN(odbc),
  342. PHP_MINFO(odbc),
  343. "1.0",
  344. PHP_MODULE_GLOBALS(odbc),
  345. PHP_GINIT(odbc),
  346. NULL,
  347. NULL,
  348. STANDARD_MODULE_PROPERTIES_EX
  349. };
  350. /* }}} */
  351. #ifdef COMPILE_DL_ODBC
  352. ZEND_GET_MODULE(odbc)
  353. #endif
  354. /* {{{ _free_odbc_result
  355. */
  356. static void _free_odbc_result(zend_rsrc_list_entry *rsrc TSRMLS_DC)
  357. {
  358. odbc_result *res = (odbc_result *)rsrc->ptr;
  359. int i;
  360. RETCODE rc;
  361. if (res) {
  362. if (res->values) {
  363. for(i = 0; i < res->numcols; i++) {
  364. if (res->values[i].value)
  365. efree(res->values[i].value);
  366. }
  367. efree(res->values);
  368. res->values = NULL;
  369. }
  370. if (res->stmt) {
  371. #if defined(HAVE_SOLID) || defined(HAVE_SOLID_30) || defined(HAVE_SOLID_35)
  372. SQLTransact(res->conn_ptr->henv, res->conn_ptr->hdbc,
  373. (SQLUSMALLINT) SQL_COMMIT);
  374. #endif
  375. rc = SQLFreeStmt(res->stmt,SQL_DROP);
  376. /* We don't want the connection to be closed after the last statment has been closed
  377. * Connections will be closed on shutdown
  378. * zend_list_delete(res->conn_ptr->id);
  379. */
  380. }
  381. efree(res);
  382. }
  383. }
  384. /* }}} */
  385. /* {{{ safe_odbc_disconnect
  386. * disconnect, and if it fails, then issue a rollback for any pending transaction (lurcher)
  387. */
  388. static void safe_odbc_disconnect( void *handle )
  389. {
  390. int ret;
  391. ret = SQLDisconnect( handle );
  392. if ( ret == SQL_ERROR )
  393. {
  394. SQLTransact( NULL, handle, SQL_ROLLBACK );
  395. SQLDisconnect( handle );
  396. }
  397. }
  398. /* }}} */
  399. /* {{{ _close_odbc_conn
  400. */
  401. static void _close_odbc_conn(zend_rsrc_list_entry *rsrc TSRMLS_DC)
  402. {
  403. int i, nument, type;
  404. void *ptr;
  405. odbc_result *res;
  406. odbc_connection *conn = (odbc_connection *)rsrc->ptr;
  407. nument = zend_hash_next_free_element(&EG(regular_list));
  408. for(i = 1; i < nument; i++) {
  409. ptr = zend_list_find(i, &type);
  410. if (ptr && (type == le_result)) {
  411. res = (odbc_result *)ptr;
  412. if (res->conn_ptr == conn) {
  413. zend_list_delete(i);
  414. }
  415. }
  416. }
  417. safe_odbc_disconnect(conn->hdbc);
  418. SQLFreeConnect(conn->hdbc);
  419. SQLFreeEnv(conn->henv);
  420. efree(conn);
  421. ODBCG(num_links)--;
  422. }
  423. /* }}} */
  424. /* {{{ void _close_odbc_pconn
  425. */
  426. static void _close_odbc_pconn(zend_rsrc_list_entry *rsrc TSRMLS_DC)
  427. {
  428. int i, nument, type;
  429. void *ptr;
  430. odbc_result *res;
  431. odbc_connection *conn = (odbc_connection *)rsrc->ptr;
  432. nument = zend_hash_next_free_element(&EG(persistent_list));
  433. for(i = 1; i < nument; i++) {
  434. ptr = zend_list_find(i, &type);
  435. if (ptr && (type == le_result)) {
  436. res = (odbc_result *)ptr;
  437. if (res->conn_ptr == conn) {
  438. zend_list_delete(i);
  439. }
  440. }
  441. }
  442. safe_odbc_disconnect(conn->hdbc);
  443. SQLFreeConnect(conn->hdbc);
  444. SQLFreeEnv(conn->henv);
  445. free(conn);
  446. ODBCG(num_links)--;
  447. ODBCG(num_persistent)--;
  448. }
  449. /* }}} */
  450. /* {{{ PHP_INI_DISP(display_link_nums)
  451. */
  452. static PHP_INI_DISP(display_link_nums)
  453. {
  454. char *value;
  455. TSRMLS_FETCH();
  456. if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
  457. value = ini_entry->orig_value;
  458. } else if (ini_entry->value) {
  459. value = ini_entry->value;
  460. } else {
  461. value = NULL;
  462. }
  463. if (value) {
  464. if (atoi(value) == -1) {
  465. PUTS("Unlimited");
  466. } else {
  467. php_printf("%s", value);
  468. }
  469. }
  470. }
  471. /* }}} */
  472. /* {{{ PHP_INI_DISP(display_defPW)
  473. */
  474. static PHP_INI_DISP(display_defPW)
  475. {
  476. char *value;
  477. TSRMLS_FETCH();
  478. if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
  479. value = ini_entry->orig_value;
  480. } else if (ini_entry->value) {
  481. value = ini_entry->value;
  482. } else {
  483. value = NULL;
  484. }
  485. if (value) {
  486. #if PHP_DEBUG
  487. php_printf("%s", value);
  488. #else
  489. PUTS("********");
  490. #endif
  491. } else {
  492. if (PG(html_errors)) {
  493. PUTS("<i>no value</i>");
  494. } else {
  495. PUTS("no value");
  496. }
  497. }
  498. }
  499. /* }}} */
  500. /* {{{ PHP_INI_DISP(display_binmode)
  501. */
  502. static PHP_INI_DISP(display_binmode)
  503. {
  504. char *value;
  505. TSRMLS_FETCH();
  506. if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
  507. value = ini_entry->orig_value;
  508. } else if (ini_entry->value) {
  509. value = ini_entry->value;
  510. } else {
  511. value = NULL;
  512. }
  513. if (value) {
  514. switch(atoi(value)) {
  515. case 0:
  516. PUTS("passthru");
  517. break;
  518. case 1:
  519. PUTS("return as is");
  520. break;
  521. case 2:
  522. PUTS("return as char");
  523. break;
  524. }
  525. }
  526. }
  527. /* }}} */
  528. /* {{{ PHP_INI_DISP(display_lrl)
  529. */
  530. static PHP_INI_DISP(display_lrl)
  531. {
  532. char *value;
  533. TSRMLS_FETCH();
  534. if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
  535. value = ini_entry->orig_value;
  536. } else if (ini_entry->value) {
  537. value = ini_entry->value;
  538. } else {
  539. value = NULL;
  540. }
  541. if (value) {
  542. if (atoi(value) <= 0) {
  543. PUTS("Passthru");
  544. } else {
  545. php_printf("return up to %s bytes", value);
  546. }
  547. }
  548. }
  549. /* }}} */
  550. /* {{{ PHP_INI_DISP(display_cursortype)
  551. */
  552. static PHP_INI_DISP(display_cursortype)
  553. {
  554. char *value;
  555. TSRMLS_FETCH();
  556. if (type == PHP_INI_DISPLAY_ORIG && ini_entry->modified) {
  557. value = ini_entry->orig_value;
  558. } else if (ini_entry->value) {
  559. value = ini_entry->value;
  560. } else {
  561. value = NULL;
  562. }
  563. if (value) {
  564. switch (atoi (value))
  565. {
  566. case SQL_CURSOR_FORWARD_ONLY:
  567. PUTS ("Forward Only cursor");
  568. break;
  569. case SQL_CURSOR_STATIC:
  570. PUTS ("Static cursor");
  571. break;
  572. case SQL_CURSOR_KEYSET_DRIVEN:
  573. PUTS ("Keyset driven cursor");
  574. break;
  575. case SQL_CURSOR_DYNAMIC:
  576. PUTS ("Dynamic cursor");
  577. break;
  578. default:
  579. php_printf("Unknown cursor model %s", value);
  580. break;
  581. }
  582. }
  583. }
  584. /* }}} */
  585. /* {{{ PHP_INI_BEGIN
  586. */
  587. PHP_INI_BEGIN()
  588. STD_PHP_INI_BOOLEAN("odbc.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateLong,
  589. allow_persistent, zend_odbc_globals, odbc_globals)
  590. STD_PHP_INI_ENTRY_EX("odbc.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong,
  591. max_persistent, zend_odbc_globals, odbc_globals, display_link_nums)
  592. STD_PHP_INI_ENTRY_EX("odbc.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong,
  593. max_links, zend_odbc_globals, odbc_globals, display_link_nums)
  594. STD_PHP_INI_ENTRY("odbc.default_db", NULL, PHP_INI_ALL, OnUpdateString,
  595. defDB, zend_odbc_globals, odbc_globals)
  596. STD_PHP_INI_ENTRY("odbc.default_user", NULL, PHP_INI_ALL, OnUpdateString,
  597. defUser, zend_odbc_globals, odbc_globals)
  598. STD_PHP_INI_ENTRY_EX("odbc.default_pw", NULL, PHP_INI_ALL, OnUpdateString,
  599. defPW, zend_odbc_globals, odbc_globals, display_defPW)
  600. STD_PHP_INI_ENTRY_EX("odbc.defaultlrl", "4096", PHP_INI_ALL, OnUpdateLong,
  601. defaultlrl, zend_odbc_globals, odbc_globals, display_lrl)
  602. STD_PHP_INI_ENTRY_EX("odbc.defaultbinmode", "1", PHP_INI_ALL, OnUpdateLong,
  603. defaultbinmode, zend_odbc_globals, odbc_globals, display_binmode)
  604. STD_PHP_INI_BOOLEAN("odbc.check_persistent", "1", PHP_INI_SYSTEM, OnUpdateLong,
  605. check_persistent, zend_odbc_globals, odbc_globals)
  606. STD_PHP_INI_ENTRY_EX("odbc.default_cursortype", "3", PHP_INI_ALL, OnUpdateLong,
  607. default_cursortype, zend_odbc_globals, odbc_globals, display_cursortype)
  608. PHP_INI_END()
  609. /* }}} */
  610. static PHP_GINIT_FUNCTION(odbc)
  611. {
  612. odbc_globals->num_persistent = 0;
  613. }
  614. /* {{{ PHP_MINIT_FUNCTION */
  615. PHP_MINIT_FUNCTION(odbc)
  616. {
  617. #ifdef SQLANY_BUG
  618. ODBC_SQL_CONN_T foobar;
  619. RETCODE rc;
  620. #endif
  621. REGISTER_INI_ENTRIES();
  622. le_result = zend_register_list_destructors_ex(_free_odbc_result, NULL, "odbc result", module_number);
  623. le_conn = zend_register_list_destructors_ex(_close_odbc_conn, NULL, "odbc link", module_number);
  624. le_pconn = zend_register_list_destructors_ex(NULL, _close_odbc_pconn, "odbc link persistent", module_number);
  625. Z_TYPE(odbc_module_entry) = type;
  626. REGISTER_STRING_CONSTANT("ODBC_TYPE", PHP_ODBC_TYPE, CONST_CS | CONST_PERSISTENT);
  627. REGISTER_LONG_CONSTANT("ODBC_BINMODE_PASSTHRU", 0, CONST_CS | CONST_PERSISTENT);
  628. REGISTER_LONG_CONSTANT("ODBC_BINMODE_RETURN", 1, CONST_CS | CONST_PERSISTENT);
  629. REGISTER_LONG_CONSTANT("ODBC_BINMODE_CONVERT", 2, CONST_CS | CONST_PERSISTENT);
  630. /* Define Constants for options
  631. these Constants are defined in <sqlext.h>
  632. */
  633. REGISTER_LONG_CONSTANT("SQL_ODBC_CURSORS", SQL_ODBC_CURSORS, CONST_PERSISTENT | CONST_CS);
  634. REGISTER_LONG_CONSTANT("SQL_CUR_USE_DRIVER", SQL_CUR_USE_DRIVER, CONST_PERSISTENT | CONST_CS);
  635. REGISTER_LONG_CONSTANT("SQL_CUR_USE_IF_NEEDED", SQL_CUR_USE_IF_NEEDED, CONST_PERSISTENT | CONST_CS);
  636. REGISTER_LONG_CONSTANT("SQL_CUR_USE_ODBC", SQL_CUR_USE_ODBC, CONST_PERSISTENT | CONST_CS);
  637. REGISTER_LONG_CONSTANT("SQL_CONCURRENCY", SQL_CONCURRENCY, CONST_PERSISTENT | CONST_CS);
  638. REGISTER_LONG_CONSTANT("SQL_CONCUR_READ_ONLY", SQL_CONCUR_READ_ONLY, CONST_PERSISTENT | CONST_CS);
  639. REGISTER_LONG_CONSTANT("SQL_CONCUR_LOCK", SQL_CONCUR_LOCK, CONST_PERSISTENT | CONST_CS);
  640. REGISTER_LONG_CONSTANT("SQL_CONCUR_ROWVER", SQL_CONCUR_ROWVER, CONST_PERSISTENT | CONST_CS);
  641. REGISTER_LONG_CONSTANT("SQL_CONCUR_VALUES", SQL_CONCUR_VALUES, CONST_PERSISTENT | CONST_CS);
  642. REGISTER_LONG_CONSTANT("SQL_CURSOR_TYPE", SQL_CURSOR_TYPE, CONST_PERSISTENT | CONST_CS);
  643. REGISTER_LONG_CONSTANT("SQL_CURSOR_FORWARD_ONLY", SQL_CURSOR_FORWARD_ONLY, CONST_PERSISTENT | CONST_CS);
  644. REGISTER_LONG_CONSTANT("SQL_CURSOR_KEYSET_DRIVEN", SQL_CURSOR_KEYSET_DRIVEN, CONST_PERSISTENT | CONST_CS);
  645. REGISTER_LONG_CONSTANT("SQL_CURSOR_DYNAMIC", SQL_CURSOR_DYNAMIC, CONST_PERSISTENT | CONST_CS);
  646. REGISTER_LONG_CONSTANT("SQL_CURSOR_STATIC", SQL_CURSOR_STATIC, CONST_PERSISTENT | CONST_CS);
  647. REGISTER_LONG_CONSTANT("SQL_KEYSET_SIZE", SQL_KEYSET_SIZE, CONST_PERSISTENT | CONST_CS);
  648. /* these are for the Data Source type */
  649. REGISTER_LONG_CONSTANT("SQL_FETCH_FIRST", SQL_FETCH_FIRST, CONST_PERSISTENT | CONST_CS);
  650. REGISTER_LONG_CONSTANT("SQL_FETCH_NEXT", SQL_FETCH_NEXT, CONST_PERSISTENT | CONST_CS);
  651. /*
  652. * register the standard data types
  653. */
  654. REGISTER_LONG_CONSTANT("SQL_CHAR", SQL_CHAR, CONST_PERSISTENT | CONST_CS);
  655. REGISTER_LONG_CONSTANT("SQL_VARCHAR", SQL_VARCHAR, CONST_PERSISTENT | CONST_CS);
  656. REGISTER_LONG_CONSTANT("SQL_LONGVARCHAR", SQL_LONGVARCHAR, CONST_PERSISTENT | CONST_CS);
  657. REGISTER_LONG_CONSTANT("SQL_DECIMAL", SQL_DECIMAL, CONST_PERSISTENT | CONST_CS);
  658. REGISTER_LONG_CONSTANT("SQL_NUMERIC", SQL_NUMERIC, CONST_PERSISTENT | CONST_CS);
  659. REGISTER_LONG_CONSTANT("SQL_BIT", SQL_BIT, CONST_PERSISTENT | CONST_CS);
  660. REGISTER_LONG_CONSTANT("SQL_TINYINT", SQL_TINYINT, CONST_PERSISTENT | CONST_CS);
  661. REGISTER_LONG_CONSTANT("SQL_SMALLINT", SQL_SMALLINT, CONST_PERSISTENT | CONST_CS);
  662. REGISTER_LONG_CONSTANT("SQL_INTEGER", SQL_INTEGER, CONST_PERSISTENT | CONST_CS);
  663. REGISTER_LONG_CONSTANT("SQL_BIGINT", SQL_BIGINT, CONST_PERSISTENT | CONST_CS);
  664. REGISTER_LONG_CONSTANT("SQL_REAL", SQL_REAL, CONST_PERSISTENT | CONST_CS);
  665. REGISTER_LONG_CONSTANT("SQL_FLOAT", SQL_FLOAT, CONST_PERSISTENT | CONST_CS);
  666. REGISTER_LONG_CONSTANT("SQL_DOUBLE", SQL_DOUBLE, CONST_PERSISTENT | CONST_CS);
  667. REGISTER_LONG_CONSTANT("SQL_BINARY", SQL_BINARY, CONST_PERSISTENT | CONST_CS);
  668. REGISTER_LONG_CONSTANT("SQL_VARBINARY", SQL_VARBINARY, CONST_PERSISTENT | CONST_CS);
  669. REGISTER_LONG_CONSTANT("SQL_LONGVARBINARY", SQL_LONGVARBINARY, CONST_PERSISTENT | CONST_CS);
  670. REGISTER_LONG_CONSTANT("SQL_DATE", SQL_DATE, CONST_PERSISTENT | CONST_CS);
  671. REGISTER_LONG_CONSTANT("SQL_TIME", SQL_TIME, CONST_PERSISTENT | CONST_CS);
  672. REGISTER_LONG_CONSTANT("SQL_TIMESTAMP", SQL_TIMESTAMP, CONST_PERSISTENT | CONST_CS);
  673. #if defined(ODBCVER) && (ODBCVER >= 0x0300)
  674. REGISTER_LONG_CONSTANT("SQL_TYPE_DATE", SQL_TYPE_DATE, CONST_PERSISTENT | CONST_CS);
  675. REGISTER_LONG_CONSTANT("SQL_TYPE_TIME", SQL_TYPE_TIME, CONST_PERSISTENT | CONST_CS);
  676. REGISTER_LONG_CONSTANT("SQL_TYPE_TIMESTAMP", SQL_TYPE_TIMESTAMP, CONST_PERSISTENT | CONST_CS);
  677. /*
  678. * SQLSpecialColumns values
  679. */
  680. REGISTER_LONG_CONSTANT("SQL_BEST_ROWID", SQL_BEST_ROWID, CONST_PERSISTENT | CONST_CS);
  681. REGISTER_LONG_CONSTANT("SQL_ROWVER", SQL_ROWVER, CONST_PERSISTENT | CONST_CS);
  682. REGISTER_LONG_CONSTANT("SQL_SCOPE_CURROW", SQL_SCOPE_CURROW, CONST_PERSISTENT | CONST_CS);
  683. REGISTER_LONG_CONSTANT("SQL_SCOPE_TRANSACTION", SQL_SCOPE_TRANSACTION, CONST_PERSISTENT | CONST_CS);
  684. REGISTER_LONG_CONSTANT("SQL_SCOPE_SESSION", SQL_SCOPE_SESSION, CONST_PERSISTENT | CONST_CS);
  685. REGISTER_LONG_CONSTANT("SQL_NO_NULLS", SQL_NO_NULLS, CONST_PERSISTENT | CONST_CS);
  686. REGISTER_LONG_CONSTANT("SQL_NULLABLE", SQL_NULLABLE, CONST_PERSISTENT | CONST_CS);
  687. /*
  688. * SQLStatistics values
  689. */
  690. REGISTER_LONG_CONSTANT("SQL_INDEX_UNIQUE", SQL_INDEX_UNIQUE, CONST_PERSISTENT | CONST_CS);
  691. REGISTER_LONG_CONSTANT("SQL_INDEX_ALL", SQL_INDEX_ALL, CONST_PERSISTENT | CONST_CS);
  692. REGISTER_LONG_CONSTANT("SQL_ENSURE", SQL_ENSURE, CONST_PERSISTENT | CONST_CS);
  693. REGISTER_LONG_CONSTANT("SQL_QUICK", SQL_QUICK, CONST_PERSISTENT | CONST_CS);
  694. #endif
  695. #if defined(HAVE_IBMDB2) && defined(_AIX)
  696. /* atexit() handler in the DB2/AIX library segfaults in PHP CLI */
  697. /* DB2NOEXITLIST env variable prevents DB2 from invoking atexit() */
  698. putenv("DB2NOEXITLIST=TRUE");
  699. #endif
  700. return SUCCESS;
  701. }
  702. /* }}} */
  703. /* {{{ PHP_RINIT_FUNCTION */
  704. PHP_RINIT_FUNCTION(odbc)
  705. {
  706. ODBCG(defConn) = -1;
  707. ODBCG(num_links) = ODBCG(num_persistent);
  708. memset(ODBCG(laststate), '\0', 6);
  709. memset(ODBCG(lasterrormsg), '\0', SQL_MAX_MESSAGE_LENGTH);
  710. return SUCCESS;
  711. }
  712. /* }}} */
  713. /* {{{ PHP_RSHUTDOWN_FUNCTION */
  714. PHP_RSHUTDOWN_FUNCTION(odbc)
  715. {
  716. return SUCCESS;
  717. }
  718. /* }}} */
  719. /* {{{ PHP_MSHUTDOWN_FUNCTION */
  720. PHP_MSHUTDOWN_FUNCTION(odbc)
  721. {
  722. UNREGISTER_INI_ENTRIES();
  723. return SUCCESS;
  724. }
  725. /* }}} */
  726. /* {{{ PHP_MINFO_FUNCTION */
  727. PHP_MINFO_FUNCTION(odbc)
  728. {
  729. char buf[32];
  730. php_info_print_table_start();
  731. php_info_print_table_header(2, "ODBC Support", "enabled");
  732. snprintf(buf, sizeof(buf), "%ld", ODBCG(num_persistent));
  733. php_info_print_table_row(2, "Active Persistent Links", buf);
  734. snprintf(buf, sizeof(buf), "%ld", ODBCG(num_links));
  735. php_info_print_table_row(2, "Active Links", buf);
  736. php_info_print_table_row(2, "ODBC library", PHP_ODBC_TYPE);
  737. #ifndef PHP_WIN32
  738. php_info_print_table_row(2, "ODBC_INCLUDE", PHP_ODBC_INCLUDE);
  739. php_info_print_table_row(2, "ODBC_LFLAGS", PHP_ODBC_LFLAGS);
  740. php_info_print_table_row(2, "ODBC_LIBS", PHP_ODBC_LIBS);
  741. #endif
  742. php_info_print_table_end();
  743. DISPLAY_INI_ENTRIES();
  744. }
  745. /* }}} */
  746. /* {{{ odbc_sql_error */
  747. void odbc_sql_error(ODBC_SQL_ERROR_PARAMS)
  748. {
  749. char state[6];
  750. SQLINTEGER error; /* Not used */
  751. char errormsg[SQL_MAX_MESSAGE_LENGTH];
  752. SQLSMALLINT errormsgsize; /* Not used */
  753. RETCODE rc;
  754. ODBC_SQL_ENV_T henv;
  755. ODBC_SQL_CONN_T conn;
  756. TSRMLS_FETCH();
  757. if (conn_resource) {
  758. henv = conn_resource->henv;
  759. conn = conn_resource->hdbc;
  760. } else {
  761. henv = SQL_NULL_HENV;
  762. conn = SQL_NULL_HDBC;
  763. }
  764. /* This leads to an endless loop in many drivers!
  765. *
  766. while(henv != SQL_NULL_HENV){
  767. do {
  768. */
  769. rc = SQLError(henv, conn, stmt, state, &error, errormsg, sizeof(errormsg)-1, &errormsgsize);
  770. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  771. snprintf(state, sizeof(state), "HY000");
  772. snprintf(errormsg, sizeof(errormsg), "Failed to fetch error message");
  773. }
  774. if (conn_resource) {
  775. memcpy(conn_resource->laststate, state, sizeof(state));
  776. memcpy(conn_resource->lasterrormsg, errormsg, sizeof(errormsg));
  777. }
  778. memcpy(ODBCG(laststate), state, sizeof(state));
  779. memcpy(ODBCG(lasterrormsg), errormsg, sizeof(errormsg));
  780. if (func) {
  781. php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQL error: %s, SQL state %s in %s", errormsg, state, func);
  782. } else {
  783. php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQL error: %s, SQL state %s", errormsg, state);
  784. }
  785. /*
  786. } while (SQL_SUCCEEDED(rc));
  787. }
  788. */
  789. }
  790. /* }}} */
  791. /* {{{ php_odbc_fetch_attribs */
  792. void php_odbc_fetch_attribs(INTERNAL_FUNCTION_PARAMETERS, int mode)
  793. {
  794. odbc_result *result;
  795. zval *pv_res;
  796. long flag;
  797. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &pv_res, &flag) == FAILURE) {
  798. return;
  799. }
  800. if (Z_LVAL_P(pv_res)) {
  801. ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
  802. if (mode) {
  803. result->longreadlen = flag;
  804. } else {
  805. result->binmode = flag;
  806. }
  807. } else {
  808. if (mode) {
  809. ODBCG(defaultlrl) = flag;
  810. } else {
  811. ODBCG(defaultbinmode) = flag;
  812. }
  813. }
  814. RETURN_TRUE;
  815. }
  816. /* }}} */
  817. /* {{{ odbc_bindcols */
  818. int odbc_bindcols(odbc_result *result TSRMLS_DC)
  819. {
  820. RETCODE rc;
  821. int i;
  822. SQLSMALLINT colnamelen; /* Not used */
  823. SQLLEN displaysize;
  824. result->values = (odbc_result_value *) safe_emalloc(sizeof(odbc_result_value), result->numcols, 0);
  825. result->longreadlen = ODBCG(defaultlrl);
  826. result->binmode = ODBCG(defaultbinmode);
  827. for(i = 0; i < result->numcols; i++) {
  828. rc = SQLColAttributes(result->stmt, (SQLUSMALLINT)(i+1), SQL_COLUMN_NAME,
  829. result->values[i].name, sizeof(result->values[i].name), &colnamelen, 0);
  830. rc = SQLColAttributes(result->stmt, (SQLUSMALLINT)(i+1), SQL_COLUMN_TYPE,
  831. NULL, 0, NULL, &result->values[i].coltype);
  832. /* Don't bind LONG / BINARY columns, so that fetch behaviour can
  833. * be controlled by odbc_binmode() / odbc_longreadlen()
  834. */
  835. switch(result->values[i].coltype) {
  836. case SQL_BINARY:
  837. case SQL_VARBINARY:
  838. case SQL_LONGVARBINARY:
  839. case SQL_LONGVARCHAR:
  840. result->values[i].value = NULL;
  841. break;
  842. #ifdef HAVE_ADABAS
  843. case SQL_TIMESTAMP:
  844. result->values[i].value = (char *)emalloc(27);
  845. SQLBindCol(result->stmt, (SQLUSMALLINT)(i+1), SQL_C_CHAR, result->values[i].value,
  846. 27, &result->values[i].vallen);
  847. break;
  848. #endif /* HAVE_ADABAS */
  849. default:
  850. rc = SQLColAttributes(result->stmt, (SQLUSMALLINT)(i+1), SQL_COLUMN_DISPLAY_SIZE,
  851. NULL, 0, NULL, &displaysize);
  852. displaysize = displaysize <= result->longreadlen ? displaysize :
  853. result->longreadlen;
  854. /* Workaround for Oracle ODBC Driver bug (#50162) when fetching TIMESTAMP column */
  855. if (result->values[i].coltype == SQL_TIMESTAMP) {
  856. displaysize += 3;
  857. }
  858. result->values[i].value = (char *)emalloc(displaysize + 1);
  859. rc = SQLBindCol(result->stmt, (SQLUSMALLINT)(i+1), SQL_C_CHAR, result->values[i].value,
  860. displaysize + 1, &result->values[i].vallen);
  861. break;
  862. }
  863. }
  864. return 1;
  865. }
  866. /* }}} */
  867. /* {{{ odbc_transact */
  868. void odbc_transact(INTERNAL_FUNCTION_PARAMETERS, int type)
  869. {
  870. odbc_connection *conn;
  871. RETCODE rc;
  872. zval *pv_conn;
  873. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_conn) == FAILURE) {
  874. return;
  875. }
  876. ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
  877. rc = SQLTransact(conn->henv, conn->hdbc, (SQLUSMALLINT)((type)?SQL_COMMIT:SQL_ROLLBACK));
  878. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  879. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLTransact");
  880. RETURN_FALSE;
  881. }
  882. RETURN_TRUE;
  883. }
  884. /* }}} */
  885. /* {{{ _close_pconn_with_id */
  886. static int _close_pconn_with_id(zend_rsrc_list_entry *le, int *id TSRMLS_DC)
  887. {
  888. if(Z_TYPE_P(le) == le_pconn && (((odbc_connection *)(le->ptr))->id == *id)){
  889. return 1;
  890. }else{
  891. return 0;
  892. }
  893. }
  894. /* }}} */
  895. /* {{{ odbc_column_lengths */
  896. void odbc_column_lengths(INTERNAL_FUNCTION_PARAMETERS, int type)
  897. {
  898. odbc_result *result;
  899. #if defined(HAVE_SOLID) || defined(HAVE_SOLID_30)
  900. /* this seems to be necessary for Solid2.3 ( tested by
  901. * tammy@synchronis.com) and Solid 3.0 (tested by eric@terra.telemediair.nl)
  902. * Solid does not seem to declare a SQLINTEGER, but it does declare a
  903. * SQL_INTEGER which does not work (despite being the same type as a SDWORD.
  904. * Solid 3.5 does not have this issue.
  905. */
  906. SDWORD len;
  907. #else
  908. SQLLEN len;
  909. #endif
  910. zval *pv_res;
  911. long pv_num;
  912. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &pv_res, &pv_num) == FAILURE) {
  913. return;
  914. }
  915. ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
  916. if (result->numcols == 0) {
  917. php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
  918. RETURN_FALSE;
  919. }
  920. if (pv_num > result->numcols) {
  921. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field index larger than number of fields");
  922. RETURN_FALSE;
  923. }
  924. if (pv_num < 1) {
  925. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field numbering starts at 1");
  926. RETURN_FALSE;
  927. }
  928. SQLColAttributes(result->stmt, (SQLUSMALLINT)pv_num, (SQLUSMALLINT) (type?SQL_COLUMN_SCALE:SQL_COLUMN_PRECISION), NULL, 0, NULL, &len);
  929. RETURN_LONG(len);
  930. }
  931. /* }}} */
  932. /* Main User Functions */
  933. /* {{{ proto void odbc_close_all(void)
  934. Close all ODBC connections */
  935. PHP_FUNCTION(odbc_close_all)
  936. {
  937. void *ptr;
  938. int type;
  939. int i;
  940. int nument;
  941. if (zend_parse_parameters_none() == FAILURE) {
  942. return;
  943. }
  944. nument = zend_hash_next_free_element(&EG(regular_list));
  945. /* Loop through list and close all statements */
  946. for(i = 1; i < nument; i++) {
  947. ptr = zend_list_find(i, &type);
  948. if (ptr && (type == le_result)){
  949. zend_list_delete(i);
  950. }
  951. }
  952. /* Second loop through list, now close all connections */
  953. nument = zend_hash_next_free_element(&EG(regular_list));
  954. for(i = 1; i < nument; i++) {
  955. ptr = zend_list_find(i, &type);
  956. if (ptr){
  957. if(type == le_conn){
  958. zend_list_delete(i);
  959. }else if(type == le_pconn){
  960. zend_list_delete(i);
  961. /* Delete the persistent connection */
  962. zend_hash_apply_with_argument(&EG(persistent_list),
  963. (apply_func_arg_t) _close_pconn_with_id, (void *) &i TSRMLS_CC);
  964. }
  965. }
  966. }
  967. }
  968. /* }}} */
  969. /* {{{ proto bool odbc_binmode(int result_id, int mode)
  970. Handle binary column data */
  971. PHP_FUNCTION(odbc_binmode)
  972. {
  973. php_odbc_fetch_attribs(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  974. }
  975. /* }}} */
  976. /* {{{ proto bool odbc_longreadlen(int result_id, int length)
  977. Handle LONG columns */
  978. PHP_FUNCTION(odbc_longreadlen)
  979. {
  980. php_odbc_fetch_attribs(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  981. }
  982. /* }}} */
  983. /* {{{ proto resource odbc_prepare(resource connection_id, string query)
  984. Prepares a statement for execution */
  985. PHP_FUNCTION(odbc_prepare)
  986. {
  987. zval *pv_conn;
  988. char *query;
  989. int query_len;
  990. odbc_result *result = NULL;
  991. odbc_connection *conn;
  992. RETCODE rc;
  993. #ifdef HAVE_SQL_EXTENDED_FETCH
  994. SQLUINTEGER scrollopts;
  995. #endif
  996. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pv_conn, &query, &query_len) == FAILURE) {
  997. return;
  998. }
  999. ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
  1000. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  1001. result->numparams = 0;
  1002. rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
  1003. if (rc == SQL_INVALID_HANDLE) {
  1004. efree(result);
  1005. php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  1006. RETURN_FALSE;
  1007. }
  1008. if (rc == SQL_ERROR) {
  1009. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  1010. efree(result);
  1011. RETURN_FALSE;
  1012. }
  1013. #ifdef HAVE_SQL_EXTENDED_FETCH
  1014. /* Solid doesn't have ExtendedFetch, if DriverManager is used, get Info,
  1015. whether Driver supports ExtendedFetch */
  1016. rc = SQLGetInfo(conn->hdbc, SQL_FETCH_DIRECTION, (void *) &scrollopts, sizeof(scrollopts), NULL);
  1017. if (rc == SQL_SUCCESS) {
  1018. if ((result->fetch_abs = (scrollopts & SQL_FD_FETCH_ABSOLUTE))) {
  1019. /* Try to set CURSOR_TYPE to dynamic. Driver will replace this with other
  1020. type if not possible.
  1021. */
  1022. SQLSetStmtOption(result->stmt, SQL_CURSOR_TYPE, ODBCG(default_cursortype));
  1023. }
  1024. } else {
  1025. result->fetch_abs = 0;
  1026. }
  1027. #endif
  1028. rc = SQLPrepare(result->stmt, query, SQL_NTS);
  1029. switch (rc) {
  1030. case SQL_SUCCESS:
  1031. break;
  1032. case SQL_SUCCESS_WITH_INFO:
  1033. odbc_sql_error(conn, result->stmt, "SQLPrepare");
  1034. break;
  1035. default:
  1036. odbc_sql_error(conn, result->stmt, "SQLPrepare");
  1037. RETURN_FALSE;
  1038. }
  1039. SQLNumParams(result->stmt, &(result->numparams));
  1040. SQLNumResultCols(result->stmt, &(result->numcols));
  1041. if (result->numcols > 0) {
  1042. if (!odbc_bindcols(result TSRMLS_CC)) {
  1043. efree(result);
  1044. RETURN_FALSE;
  1045. }
  1046. } else {
  1047. result->values = NULL;
  1048. }
  1049. zend_list_addref(conn->id);
  1050. result->conn_ptr = conn;
  1051. result->fetched = 0;
  1052. ZEND_REGISTER_RESOURCE(return_value, result, le_result);
  1053. }
  1054. /* }}} */
  1055. /*
  1056. * Execute prepared SQL statement. Supports only input parameters.
  1057. */
  1058. /* {{{ proto bool odbc_execute(resource result_id [, array parameters_array])
  1059. Execute a prepared statement */
  1060. PHP_FUNCTION(odbc_execute)
  1061. {
  1062. zval *pv_res, *pv_param_arr, **tmp;
  1063. typedef struct params_t {
  1064. SQLLEN vallen;
  1065. int fp;
  1066. } params_t;
  1067. params_t *params = NULL;
  1068. char *filename;
  1069. unsigned char otype;
  1070. SQLSMALLINT sqltype, ctype, scale;
  1071. SQLSMALLINT nullable;
  1072. SQLULEN precision;
  1073. odbc_result *result;
  1074. int numArgs, i, ne;
  1075. RETCODE rc;
  1076. numArgs = ZEND_NUM_ARGS();
  1077. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|a", &pv_res, &pv_param_arr) == FAILURE) {
  1078. return;
  1079. }
  1080. ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
  1081. /* XXX check for already bound parameters*/
  1082. if (result->numparams > 0 && numArgs == 1) {
  1083. php_error_docref(NULL TSRMLS_CC, E_WARNING, "No parameters to SQL statement given");
  1084. RETURN_FALSE;
  1085. }
  1086. if (result->numparams > 0) {
  1087. if ((ne = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr))) < result->numparams) {
  1088. php_error_docref(NULL TSRMLS_CC, E_WARNING,"Not enough parameters (%d should be %d) given", ne, result->numparams);
  1089. RETURN_FALSE;
  1090. }
  1091. zend_hash_internal_pointer_reset(Z_ARRVAL_P(pv_param_arr));
  1092. params = (params_t *)safe_emalloc(sizeof(params_t), result->numparams, 0);
  1093. for(i = 0; i < result->numparams; i++) {
  1094. params[i].fp = -1;
  1095. }
  1096. for(i = 1; i <= result->numparams; i++) {
  1097. if (zend_hash_get_current_data(Z_ARRVAL_P(pv_param_arr), (void **) &tmp) == FAILURE) {
  1098. php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error getting parameter");
  1099. SQLFreeStmt(result->stmt,SQL_RESET_PARAMS);
  1100. for (i = 0; i < result->numparams; i++) {
  1101. if (params[i].fp != -1) {
  1102. close(params[i].fp);
  1103. }
  1104. }
  1105. efree(params);
  1106. RETURN_FALSE;
  1107. }
  1108. otype = (*tmp)->type;
  1109. convert_to_string_ex(tmp);
  1110. if (Z_TYPE_PP(tmp) != IS_STRING) {
  1111. php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error converting parameter");
  1112. SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
  1113. for (i = 0; i < result->numparams; i++) {
  1114. if (params[i].fp != -1) {
  1115. close(params[i].fp);
  1116. }
  1117. }
  1118. efree(params);
  1119. RETURN_FALSE;
  1120. }
  1121. rc = SQLDescribeParam(result->stmt, (SQLUSMALLINT)i, &sqltype, &precision, &scale, &nullable);
  1122. params[i-1].vallen = Z_STRLEN_PP(tmp);
  1123. params[i-1].fp = -1;
  1124. if (rc == SQL_ERROR) {
  1125. odbc_sql_error(result->conn_ptr, result->stmt, "SQLDescribeParameter");
  1126. SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
  1127. for (i = 0; i < result->numparams; i++) {
  1128. if (params[i].fp != -1) {
  1129. close(params[i].fp);
  1130. }
  1131. }
  1132. efree(params);
  1133. RETURN_FALSE;
  1134. }
  1135. if (IS_SQL_BINARY(sqltype)) {
  1136. ctype = SQL_C_BINARY;
  1137. } else {
  1138. ctype = SQL_C_CHAR;
  1139. }
  1140. if (Z_STRLEN_PP(tmp) > 2 &&
  1141. Z_STRVAL_PP(tmp)[0] == '\'' &&
  1142. Z_STRVAL_PP(tmp)[Z_STRLEN_PP(tmp) - 1] == '\'') {
  1143. if (strlen(tmp) != Z_STRLEN_PP(tmp)) {
  1144. RETURN_FALSE;
  1145. }
  1146. filename = estrndup(&Z_STRVAL_PP(tmp)[1], Z_STRLEN_PP(tmp) - 2);
  1147. /* Check for safe mode. */
  1148. if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
  1149. efree(filename);
  1150. efree(params);
  1151. RETURN_FALSE;
  1152. }
  1153. /* Check the basedir */
  1154. if (php_check_open_basedir(filename TSRMLS_CC)) {
  1155. efree(filename);
  1156. SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
  1157. for (i = 0; i < result->numparams; i++) {
  1158. if (params[i].fp != -1) {
  1159. close(params[i].fp);
  1160. }
  1161. }
  1162. efree(params);
  1163. RETURN_FALSE;
  1164. }
  1165. if ((params[i-1].fp = open(filename,O_RDONLY)) == -1) {
  1166. php_error_docref(NULL TSRMLS_CC, E_WARNING,"Can't open file %s", filename);
  1167. SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
  1168. for (i = 0; i < result->numparams; i++) {
  1169. if (params[i].fp != -1) {
  1170. close(params[i].fp);
  1171. }
  1172. }
  1173. efree(params);
  1174. efree(filename);
  1175. RETURN_FALSE;
  1176. }
  1177. efree(filename);
  1178. params[i-1].vallen = SQL_LEN_DATA_AT_EXEC(0);
  1179. rc = SQLBindParameter(result->stmt, (SQLUSMALLINT)i, SQL_PARAM_INPUT,
  1180. ctype, sqltype, precision, scale,
  1181. (void *)params[i-1].fp, 0,
  1182. &params[i-1].vallen);
  1183. } else {
  1184. #ifdef HAVE_DBMAKER
  1185. precision = params[i-1].vallen;
  1186. #endif
  1187. if (otype == IS_NULL) {
  1188. params[i-1].vallen = SQL_NULL_DATA;
  1189. }
  1190. rc = SQLBindParameter(result->stmt, (SQLUSMALLINT)i, SQL_PARAM_INPUT,
  1191. ctype, sqltype, precision, scale,
  1192. Z_STRVAL_PP(tmp), 0,
  1193. &params[i-1].vallen);
  1194. }
  1195. if (rc == SQL_ERROR) {
  1196. odbc_sql_error(result->conn_ptr, result->stmt, "SQLBindParameter");
  1197. SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
  1198. for (i = 0; i < result->numparams; i++) {
  1199. if (params[i].fp != -1) {
  1200. close(params[i].fp);
  1201. }
  1202. }
  1203. efree(params);
  1204. RETURN_FALSE;
  1205. }
  1206. zend_hash_move_forward(Z_ARRVAL_P(pv_param_arr));
  1207. }
  1208. }
  1209. /* Close cursor, needed for doing multiple selects */
  1210. rc = SQLFreeStmt(result->stmt, SQL_CLOSE);
  1211. if (rc == SQL_ERROR) {
  1212. odbc_sql_error(result->conn_ptr, result->stmt, "SQLFreeStmt");
  1213. }
  1214. rc = SQLExecute(result->stmt);
  1215. result->fetched = 0;
  1216. if (rc == SQL_NEED_DATA) {
  1217. char buf[4096];
  1218. int fp, nbytes;
  1219. while (rc == SQL_NEED_DATA) {
  1220. rc = SQLParamData(result->stmt, (void*)&fp);
  1221. if (rc == SQL_NEED_DATA) {
  1222. while ((nbytes = read(fp, &buf, 4096)) > 0) {
  1223. SQLPutData(result->stmt, (void*)&buf, nbytes);
  1224. }
  1225. }
  1226. }
  1227. } else {
  1228. switch (rc) {
  1229. case SQL_SUCCESS:
  1230. break;
  1231. case SQL_NO_DATA_FOUND:
  1232. case SQL_SUCCESS_WITH_INFO:
  1233. odbc_sql_error(result->conn_ptr, result->stmt, "SQLExecute");
  1234. break;
  1235. default:
  1236. odbc_sql_error(result->conn_ptr, result->stmt, "SQLExecute");
  1237. RETVAL_FALSE;
  1238. }
  1239. }
  1240. if (result->numparams > 0) {
  1241. SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
  1242. for(i = 0; i < result->numparams; i++) {
  1243. if (params[i].fp != -1) {
  1244. close(params[i].fp);
  1245. }
  1246. }
  1247. efree(params);
  1248. }
  1249. if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO || rc == SQL_NO_DATA_FOUND) {
  1250. RETVAL_TRUE;
  1251. }
  1252. if (result->numcols == 0) {
  1253. SQLNumResultCols(result->stmt, &(result->numcols));
  1254. if (result->numcols > 0) {
  1255. if (!odbc_bindcols(result TSRMLS_CC)) {
  1256. efree(result);
  1257. RETVAL_FALSE;
  1258. }
  1259. } else {
  1260. result->values = NULL;
  1261. }
  1262. }
  1263. }
  1264. /* }}} */
  1265. /* {{{ proto string odbc_cursor(resource result_id)
  1266. Get cursor name */
  1267. PHP_FUNCTION(odbc_cursor)
  1268. {
  1269. zval *pv_res;
  1270. SQLUSMALLINT max_len;
  1271. SQLSMALLINT len;
  1272. char *cursorname;
  1273. odbc_result *result;
  1274. RETCODE rc;
  1275. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) {
  1276. return;
  1277. }
  1278. ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
  1279. rc = SQLGetInfo(result->conn_ptr->hdbc,SQL_MAX_CURSOR_NAME_LEN, (void *)&max_len,sizeof(max_len),&len);
  1280. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  1281. RETURN_FALSE;
  1282. }
  1283. if (max_len > 0) {
  1284. cursorname = emalloc(max_len + 1);
  1285. rc = SQLGetCursorName(result->stmt,cursorname,(SQLSMALLINT)max_len,&len);
  1286. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  1287. char state[6]; /* Not used */
  1288. SQLINTEGER error; /* Not used */
  1289. char errormsg[SQL_MAX_MESSAGE_LENGTH];
  1290. SQLSMALLINT errormsgsize; /* Not used */
  1291. SQLError( result->conn_ptr->henv, result->conn_ptr->hdbc,
  1292. result->stmt, state, &error, errormsg,
  1293. sizeof(errormsg)-1, &errormsgsize);
  1294. if (!strncmp(state,"S1015",5)) {
  1295. snprintf(cursorname, max_len+1, "php_curs_%d", (int)result->stmt);
  1296. if (SQLSetCursorName(result->stmt,cursorname,SQL_NTS) != SQL_SUCCESS) {
  1297. odbc_sql_error(result->conn_ptr, result->stmt, "SQLSetCursorName");
  1298. RETVAL_FALSE;
  1299. } else {
  1300. RETVAL_STRING(cursorname,1);
  1301. }
  1302. } else {
  1303. php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQL error: %s, SQL state %s", errormsg, state);
  1304. RETVAL_FALSE;
  1305. }
  1306. } else {
  1307. RETVAL_STRING(cursorname,1);
  1308. }
  1309. efree(cursorname);
  1310. } else {
  1311. RETVAL_FALSE;
  1312. }
  1313. }
  1314. /* }}} */
  1315. #ifdef HAVE_SQLDATASOURCES
  1316. /* {{{ proto array odbc_data_source(resource connection_id, int fetch_type)
  1317. Return information about the currently connected data source */
  1318. PHP_FUNCTION(odbc_data_source)
  1319. {
  1320. zval *zv_conn;
  1321. long zv_fetch_type;
  1322. RETCODE rc = 0; /* assume all is good */
  1323. odbc_connection *conn;
  1324. UCHAR server_name[100], desc[200];
  1325. SQLSMALLINT len1=0, len2=0, fetch_type;
  1326. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zv_conn, &zv_fetch_type) == FAILURE) {
  1327. return;
  1328. }
  1329. fetch_type = (SQLSMALLINT) zv_fetch_type;
  1330. if (!(fetch_type == SQL_FETCH_FIRST || fetch_type == SQL_FETCH_NEXT)) {
  1331. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid fetch type (%d)", fetch_type);
  1332. RETURN_FALSE;
  1333. }
  1334. ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &zv_conn, -1, "ODBC-Link", le_conn, le_pconn);
  1335. /* now we have the "connection" lets call the DataSource object */
  1336. rc = SQLDataSources(conn->henv,
  1337. fetch_type,
  1338. server_name,
  1339. (SQLSMALLINT)sizeof(server_name),
  1340. &len1,
  1341. desc,
  1342. (SQLSMALLINT)sizeof(desc),
  1343. &len2);
  1344. if (rc != SQL_SUCCESS) {
  1345. /* ummm.... he did it */
  1346. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLDataSources");
  1347. RETURN_FALSE;
  1348. }
  1349. if (len1 == 0 || len2 == 0) {
  1350. /* we have a non-valid entry... so stop the looping */
  1351. RETURN_FALSE;
  1352. }
  1353. array_init(return_value);
  1354. add_assoc_string_ex(return_value, "server", sizeof("server"), server_name, 1);
  1355. add_assoc_string_ex(return_value, "description", sizeof("description"), desc, 1);
  1356. }
  1357. /* }}} */
  1358. #endif /* HAVE_SQLDATASOURCES */
  1359. /* {{{ proto resource odbc_exec(resource connection_id, string query [, int flags])
  1360. Prepare and execute an SQL statement */
  1361. /* XXX Use flags */
  1362. PHP_FUNCTION(odbc_exec)
  1363. {
  1364. zval *pv_conn;
  1365. long pv_flags;
  1366. char *query;
  1367. int numArgs, query_len;
  1368. odbc_result *result = NULL;
  1369. odbc_connection *conn;
  1370. RETCODE rc;
  1371. #ifdef HAVE_SQL_EXTENDED_FETCH
  1372. SQLUINTEGER scrollopts;
  1373. #endif
  1374. numArgs = ZEND_NUM_ARGS();
  1375. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &pv_conn, &query, &query_len, &pv_flags) == FAILURE) {
  1376. return;
  1377. }
  1378. ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
  1379. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  1380. rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
  1381. if (rc == SQL_INVALID_HANDLE) {
  1382. php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  1383. efree(result);
  1384. RETURN_FALSE;
  1385. }
  1386. if (rc == SQL_ERROR) {
  1387. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  1388. efree(result);
  1389. RETURN_FALSE;
  1390. }
  1391. #ifdef HAVE_SQL_EXTENDED_FETCH
  1392. /* Solid doesn't have ExtendedFetch, if DriverManager is used, get Info,
  1393. whether Driver supports ExtendedFetch */
  1394. rc = SQLGetInfo(conn->hdbc, SQL_FETCH_DIRECTION, (void *) &scrollopts, sizeof(scrollopts), NULL);
  1395. if (rc == SQL_SUCCESS) {
  1396. if ((result->fetch_abs = (scrollopts & SQL_FD_FETCH_ABSOLUTE))) {
  1397. /* Try to set CURSOR_TYPE to dynamic. Driver will replace this with other
  1398. type if not possible.
  1399. */
  1400. SQLSetStmtOption(result->stmt, SQL_CURSOR_TYPE, ODBCG(default_cursortype));
  1401. }
  1402. } else {
  1403. result->fetch_abs = 0;
  1404. }
  1405. #endif
  1406. rc = SQLExecDirect(result->stmt, query, SQL_NTS);
  1407. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO && rc != SQL_NO_DATA_FOUND) {
  1408. /* XXX FIXME we should really check out SQLSTATE with SQLError
  1409. * in case rc is SQL_SUCCESS_WITH_INFO here.
  1410. */
  1411. odbc_sql_error(conn, result->stmt, "SQLExecDirect");
  1412. SQLFreeStmt(result->stmt, SQL_DROP);
  1413. efree(result);
  1414. RETURN_FALSE;
  1415. }
  1416. SQLNumResultCols(result->stmt, &(result->numcols));
  1417. /* For insert, update etc. cols == 0 */
  1418. if (result->numcols > 0) {
  1419. if (!odbc_bindcols(result TSRMLS_CC)) {
  1420. efree(result);
  1421. RETURN_FALSE;
  1422. }
  1423. } else {
  1424. result->values = NULL;
  1425. }
  1426. zend_list_addref(conn->id);
  1427. result->conn_ptr = conn;
  1428. result->fetched = 0;
  1429. ZEND_REGISTER_RESOURCE(return_value, result, le_result);
  1430. }
  1431. /* }}} */
  1432. #ifdef PHP_ODBC_HAVE_FETCH_HASH
  1433. #define ODBC_NUM 1
  1434. #define ODBC_OBJECT 2
  1435. /* {{{ php_odbc_fetch_hash */
  1436. static void php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int result_type)
  1437. {
  1438. int i;
  1439. odbc_result *result;
  1440. RETCODE rc;
  1441. SQLSMALLINT sql_c_type;
  1442. char *buf = NULL;
  1443. #ifdef HAVE_SQL_EXTENDED_FETCH
  1444. SQLULEN crow;
  1445. SQLUSMALLINT RowStatus[1];
  1446. SQLLEN rownum;
  1447. zval *pv_res, *tmp;
  1448. long pv_row = -1;
  1449. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &pv_res, &pv_row) == FAILURE) {
  1450. return;
  1451. }
  1452. rownum = pv_row;
  1453. #else
  1454. zval *pv_res, *tmp;
  1455. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) {
  1456. return;
  1457. }
  1458. #endif
  1459. ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
  1460. if (result->numcols == 0) {
  1461. php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
  1462. RETURN_FALSE;
  1463. }
  1464. #ifdef HAVE_SQL_EXTENDED_FETCH
  1465. if (result->fetch_abs) {
  1466. if (rownum > 0) {
  1467. rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,rownum,&crow,RowStatus);
  1468. } else {
  1469. rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
  1470. }
  1471. } else
  1472. #endif
  1473. rc = SQLFetch(result->stmt);
  1474. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  1475. RETURN_FALSE;
  1476. }
  1477. array_init(return_value);
  1478. #ifdef HAVE_SQL_EXTENDED_FETCH
  1479. if (rownum > 0 && result->fetch_abs)
  1480. result->fetched = rownum;
  1481. else
  1482. #endif
  1483. result->fetched++;
  1484. for(i = 0; i < result->numcols; i++) {
  1485. ALLOC_INIT_ZVAL(tmp);
  1486. Z_TYPE_P(tmp) = IS_STRING;
  1487. Z_STRLEN_P(tmp) = 0;
  1488. sql_c_type = SQL_C_CHAR;
  1489. switch(result->values[i].coltype) {
  1490. case SQL_BINARY:
  1491. case SQL_VARBINARY:
  1492. case SQL_LONGVARBINARY:
  1493. if (result->binmode <= 0) {
  1494. Z_STRVAL_P(tmp) = STR_EMPTY_ALLOC();
  1495. break;
  1496. }
  1497. if (result->binmode == 1) {
  1498. sql_c_type = SQL_C_BINARY;
  1499. }
  1500. case SQL_LONGVARCHAR:
  1501. if (IS_SQL_LONG(result->values[i].coltype) && result->longreadlen <= 0) {
  1502. Z_STRVAL_P(tmp) = STR_EMPTY_ALLOC();
  1503. break;
  1504. }
  1505. if (buf == NULL) {
  1506. buf = emalloc(result->longreadlen + 1);
  1507. }
  1508. rc = SQLGetData(result->stmt, (SQLUSMALLINT)(i + 1), sql_c_type, buf, result->longreadlen + 1, &result->values[i].vallen);
  1509. if (rc == SQL_ERROR) {
  1510. odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
  1511. efree(buf);
  1512. RETURN_FALSE;
  1513. }
  1514. if (rc == SQL_SUCCESS_WITH_INFO) {
  1515. Z_STRLEN_P(tmp) = result->longreadlen;
  1516. } else if (result->values[i].vallen == SQL_NULL_DATA) {
  1517. ZVAL_NULL(tmp);
  1518. break;
  1519. } else {
  1520. Z_STRLEN_P(tmp) = result->values[i].vallen;
  1521. }
  1522. Z_STRVAL_P(tmp) = estrndup(buf, Z_STRLEN_P(tmp));
  1523. break;
  1524. default:
  1525. if (result->values[i].vallen == SQL_NULL_DATA) {
  1526. ZVAL_NULL(tmp);
  1527. break;
  1528. }
  1529. Z_STRLEN_P(tmp) = result->values[i].vallen;
  1530. Z_STRVAL_P(tmp) = estrndup(result->values[i].value,Z_STRLEN_P(tmp));
  1531. break;
  1532. }
  1533. if (result_type & ODBC_NUM) {
  1534. zend_hash_index_update(Z_ARRVAL_P(return_value), i, &tmp, sizeof(zval *), NULL);
  1535. } else {
  1536. if (!*(result->values[i].name)) {
  1537. zend_hash_update(Z_ARRVAL_P(return_value), Z_STRVAL_P(tmp), Z_STRLEN_P(tmp)+1, &tmp, sizeof(zval *), NULL);
  1538. } else {
  1539. zend_hash_update(Z_ARRVAL_P(return_value), result->values[i].name, strlen(result->values[i].name)+1, &tmp, sizeof(zval *), NULL);
  1540. }
  1541. }
  1542. }
  1543. if (buf) {
  1544. efree(buf);
  1545. }
  1546. }
  1547. /* }}} */
  1548. /* {{{ proto object odbc_fetch_object(int result [, int rownumber])
  1549. Fetch a result row as an object */
  1550. PHP_FUNCTION(odbc_fetch_object)
  1551. {
  1552. php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, ODBC_OBJECT);
  1553. if (Z_TYPE_P(return_value) == IS_ARRAY) {
  1554. object_and_properties_init(return_value, ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value));
  1555. }
  1556. }
  1557. /* }}} */
  1558. /* {{{ proto array odbc_fetch_array(int result [, int rownumber])
  1559. Fetch a result row as an associative array */
  1560. PHP_FUNCTION(odbc_fetch_array)
  1561. {
  1562. php_odbc_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, ODBC_OBJECT);
  1563. }
  1564. /* }}} */
  1565. #endif
  1566. /* {{{ proto int odbc_fetch_into(resource result_id, array &result_array, [, int rownumber])
  1567. Fetch one result row into an array */
  1568. PHP_FUNCTION(odbc_fetch_into)
  1569. {
  1570. int i;
  1571. odbc_result *result;
  1572. RETCODE rc;
  1573. SQLSMALLINT sql_c_type;
  1574. char *buf = NULL;
  1575. zval *pv_res, **pv_res_arr, *tmp;
  1576. #ifdef HAVE_SQL_EXTENDED_FETCH
  1577. long pv_row = 0;
  1578. SQLULEN crow;
  1579. SQLUSMALLINT RowStatus[1];
  1580. SQLLEN rownum = -1;
  1581. #endif /* HAVE_SQL_EXTENDED_FETCH */
  1582. #ifdef HAVE_SQL_EXTENDED_FETCH
  1583. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ|l", &pv_res, &pv_res_arr, &pv_row) == FAILURE) {
  1584. return;
  1585. }
  1586. rownum = pv_row;
  1587. #else
  1588. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pv_res, &pv_res_arr) == FAILURE) {
  1589. return;
  1590. }
  1591. #endif /* HAVE_SQL_EXTENDED_FETCH */
  1592. ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
  1593. if (result->numcols == 0) {
  1594. php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
  1595. RETURN_FALSE;
  1596. }
  1597. if (Z_TYPE_PP(pv_res_arr) != IS_ARRAY) {
  1598. array_init(*pv_res_arr);
  1599. }
  1600. #ifdef HAVE_SQL_EXTENDED_FETCH
  1601. if (result->fetch_abs) {
  1602. if (rownum > 0) {
  1603. rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,rownum,&crow,RowStatus);
  1604. } else {
  1605. rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
  1606. }
  1607. } else
  1608. #endif
  1609. rc = SQLFetch(result->stmt);
  1610. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  1611. RETURN_FALSE;
  1612. }
  1613. #ifdef HAVE_SQL_EXTENDED_FETCH
  1614. if (rownum > 0 && result->fetch_abs)
  1615. result->fetched = rownum;
  1616. else
  1617. #endif
  1618. result->fetched++;
  1619. for(i = 0; i < result->numcols; i++) {
  1620. MAKE_STD_ZVAL(tmp);
  1621. Z_TYPE_P(tmp) = IS_STRING;
  1622. Z_STRLEN_P(tmp) = 0;
  1623. sql_c_type = SQL_C_CHAR;
  1624. switch(result->values[i].coltype) {
  1625. case SQL_BINARY:
  1626. case SQL_VARBINARY:
  1627. case SQL_LONGVARBINARY:
  1628. if (result->binmode <= 0) {
  1629. Z_STRVAL_P(tmp) = STR_EMPTY_ALLOC();
  1630. break;
  1631. }
  1632. if (result->binmode == 1) sql_c_type = SQL_C_BINARY;
  1633. case SQL_LONGVARCHAR:
  1634. if (IS_SQL_LONG(result->values[i].coltype) && result->longreadlen <= 0) {
  1635. Z_STRVAL_P(tmp) = STR_EMPTY_ALLOC();
  1636. break;
  1637. }
  1638. if (buf == NULL) {
  1639. buf = emalloc(result->longreadlen + 1);
  1640. }
  1641. rc = SQLGetData(result->stmt, (SQLUSMALLINT)(i + 1),sql_c_type, buf, result->longreadlen + 1, &result->values[i].vallen);
  1642. if (rc == SQL_ERROR) {
  1643. odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
  1644. efree(buf);
  1645. RETURN_FALSE;
  1646. }
  1647. if (rc == SQL_SUCCESS_WITH_INFO) {
  1648. Z_STRLEN_P(tmp) = result->longreadlen;
  1649. } else if (result->values[i].vallen == SQL_NULL_DATA) {
  1650. ZVAL_NULL(tmp);
  1651. break;
  1652. } else {
  1653. Z_STRLEN_P(tmp) = result->values[i].vallen;
  1654. }
  1655. Z_STRVAL_P(tmp) = estrndup(buf, Z_STRLEN_P(tmp));
  1656. break;
  1657. default:
  1658. if (result->values[i].vallen == SQL_NULL_DATA) {
  1659. ZVAL_NULL(tmp);
  1660. break;
  1661. }
  1662. Z_STRLEN_P(tmp) = result->values[i].vallen;
  1663. Z_STRVAL_P(tmp) = estrndup(result->values[i].value,Z_STRLEN_P(tmp));
  1664. break;
  1665. }
  1666. zend_hash_index_update(Z_ARRVAL_PP(pv_res_arr), i, &tmp, sizeof(zval *), NULL);
  1667. }
  1668. if (buf) efree(buf);
  1669. RETURN_LONG(result->numcols);
  1670. }
  1671. /* }}} */
  1672. /* {{{ proto bool solid_fetch_prev(resource result_id)
  1673. */
  1674. #if defined(HAVE_SOLID) || defined(HAVE_SOLID_30) || defined(HAVE_SOLID_35)
  1675. PHP_FUNCTION(solid_fetch_prev)
  1676. {
  1677. odbc_result *result;
  1678. RETCODE rc;
  1679. zval *pv_res;
  1680. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) {
  1681. return;
  1682. }
  1683. ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
  1684. if (result->numcols == 0) {
  1685. php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
  1686. RETURN_FALSE;
  1687. }
  1688. rc = SQLFetchPrev(result->stmt);
  1689. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  1690. RETURN_FALSE;
  1691. }
  1692. if (result->fetched > 1) {
  1693. result->fetched--;
  1694. }
  1695. RETURN_TRUE;
  1696. }
  1697. #endif
  1698. /* }}} */
  1699. /* {{{ proto bool odbc_fetch_row(resource result_id [, int row_number])
  1700. Fetch a row */
  1701. PHP_FUNCTION(odbc_fetch_row)
  1702. {
  1703. SQLLEN rownum;
  1704. odbc_result *result;
  1705. RETCODE rc;
  1706. zval *pv_res;
  1707. long pv_row = 1;
  1708. #ifdef HAVE_SQL_EXTENDED_FETCH
  1709. SQLULEN crow;
  1710. SQLUSMALLINT RowStatus[1];
  1711. #endif
  1712. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &pv_res, &pv_row) == FAILURE) {
  1713. return;
  1714. }
  1715. rownum = pv_row;
  1716. ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
  1717. if (result->numcols == 0) {
  1718. php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
  1719. RETURN_FALSE;
  1720. }
  1721. #ifdef HAVE_SQL_EXTENDED_FETCH
  1722. if (result->fetch_abs) {
  1723. if (ZEND_NUM_ARGS() > 1) {
  1724. rc = SQLExtendedFetch(result->stmt,SQL_FETCH_ABSOLUTE,rownum,&crow,RowStatus);
  1725. } else {
  1726. rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
  1727. }
  1728. } else
  1729. #endif
  1730. rc = SQLFetch(result->stmt);
  1731. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  1732. RETURN_FALSE;
  1733. }
  1734. if (ZEND_NUM_ARGS() > 1) {
  1735. result->fetched = rownum;
  1736. } else {
  1737. result->fetched++;
  1738. }
  1739. RETURN_TRUE;
  1740. }
  1741. /* }}} */
  1742. /* {{{ proto mixed odbc_result(resource result_id, mixed field)
  1743. Get result data */
  1744. PHP_FUNCTION(odbc_result)
  1745. {
  1746. char *field;
  1747. int field_ind;
  1748. SQLSMALLINT sql_c_type = SQL_C_CHAR;
  1749. odbc_result *result;
  1750. int i = 0;
  1751. RETCODE rc;
  1752. SQLLEN fieldsize;
  1753. zval *pv_res, **pv_field;
  1754. #ifdef HAVE_SQL_EXTENDED_FETCH
  1755. SQLULEN crow;
  1756. SQLUSMALLINT RowStatus[1];
  1757. #endif
  1758. field_ind = -1;
  1759. field = NULL;
  1760. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &pv_res, &pv_field) == FAILURE) {
  1761. return;
  1762. }
  1763. if (Z_TYPE_PP(pv_field) == IS_STRING) {
  1764. field = Z_STRVAL_PP(pv_field);
  1765. } else {
  1766. convert_to_long_ex(pv_field);
  1767. field_ind = Z_LVAL_PP(pv_field) - 1;
  1768. }
  1769. ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
  1770. if ((result->numcols == 0)) {
  1771. php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
  1772. RETURN_FALSE;
  1773. }
  1774. /* get field index if the field parameter was a string */
  1775. if (field != NULL) {
  1776. if (result->values == NULL) {
  1777. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Result set contains no data");
  1778. RETURN_FALSE;
  1779. }
  1780. for(i = 0; i < result->numcols; i++) {
  1781. if (!strcasecmp(result->values[i].name, field)) {
  1782. field_ind = i;
  1783. break;
  1784. }
  1785. }
  1786. if (field_ind < 0) {
  1787. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field %s not found", field);
  1788. RETURN_FALSE;
  1789. }
  1790. } else {
  1791. /* check for limits of field_ind if the field parameter was an int */
  1792. if (field_ind >= result->numcols || field_ind < 0) {
  1793. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field index is larger than the number of fields");
  1794. RETURN_FALSE;
  1795. }
  1796. }
  1797. if (result->fetched == 0) {
  1798. /* User forgot to call odbc_fetch_row(), or wants to reload the results, do it now */
  1799. #ifdef HAVE_SQL_EXTENDED_FETCH
  1800. if (result->fetch_abs)
  1801. rc = SQLExtendedFetch(result->stmt, SQL_FETCH_NEXT, 1, &crow,RowStatus);
  1802. else
  1803. #endif
  1804. rc = SQLFetch(result->stmt);
  1805. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  1806. RETURN_FALSE;
  1807. }
  1808. result->fetched++;
  1809. }
  1810. switch(result->values[field_ind].coltype) {
  1811. case SQL_BINARY:
  1812. case SQL_VARBINARY:
  1813. case SQL_LONGVARBINARY:
  1814. if (result->binmode <= 1) {
  1815. sql_c_type = SQL_C_BINARY;
  1816. }
  1817. if (result->binmode <= 0) {
  1818. break;
  1819. }
  1820. case SQL_LONGVARCHAR:
  1821. if (IS_SQL_LONG(result->values[field_ind].coltype)) {
  1822. if (result->longreadlen <= 0) {
  1823. break;
  1824. } else {
  1825. fieldsize = result->longreadlen;
  1826. }
  1827. } else {
  1828. SQLColAttributes(result->stmt, (SQLUSMALLINT)(field_ind + 1),
  1829. (SQLUSMALLINT)((sql_c_type == SQL_C_BINARY) ? SQL_COLUMN_LENGTH :
  1830. SQL_COLUMN_DISPLAY_SIZE),
  1831. NULL, 0, NULL, &fieldsize);
  1832. }
  1833. /* For char data, the length of the returned string will be longreadlen - 1 */
  1834. fieldsize = (result->longreadlen <= 0) ? 4096 : result->longreadlen;
  1835. field = emalloc(fieldsize);
  1836. /* SQLGetData will truncate CHAR data to fieldsize - 1 bytes and append \0.
  1837. * For binary data it is truncated to fieldsize bytes.
  1838. */
  1839. rc = SQLGetData(result->stmt, (SQLUSMALLINT)(field_ind + 1), sql_c_type,
  1840. field, fieldsize, &result->values[field_ind].vallen);
  1841. if (rc == SQL_ERROR) {
  1842. odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
  1843. efree(field);
  1844. RETURN_FALSE;
  1845. }
  1846. if (result->values[field_ind].vallen == SQL_NULL_DATA) {
  1847. efree(field);
  1848. RETURN_NULL();
  1849. } else if (rc == SQL_NO_DATA_FOUND) {
  1850. efree(field);
  1851. RETURN_FALSE;
  1852. }
  1853. /* Reduce fieldlen by 1 if we have char data. One day we might
  1854. have binary strings... */
  1855. if (result->values[field_ind].coltype == SQL_LONGVARCHAR) {
  1856. fieldsize -= 1;
  1857. }
  1858. /* Don't duplicate result, saves one emalloc.
  1859. For SQL_SUCCESS, the length is in vallen.
  1860. */
  1861. RETURN_STRINGL(field, (rc == SQL_SUCCESS_WITH_INFO) ? fieldsize : result->values[field_ind].vallen, 0);
  1862. break;
  1863. default:
  1864. if (result->values[field_ind].vallen == SQL_NULL_DATA) {
  1865. RETURN_NULL();
  1866. } else {
  1867. RETURN_STRINGL(result->values[field_ind].value, result->values[field_ind].vallen, 1);
  1868. }
  1869. break;
  1870. }
  1871. /* If we come here, output unbound LONG and/or BINARY column data to the client */
  1872. /* We emalloc 1 byte more for SQL_C_CHAR (trailing \0) */
  1873. fieldsize = (sql_c_type == SQL_C_CHAR) ? 4096 : 4095;
  1874. field = emalloc(fieldsize);
  1875. /* Call SQLGetData() until SQL_SUCCESS is returned */
  1876. while(1) {
  1877. rc = SQLGetData(result->stmt, (SQLUSMALLINT)(field_ind + 1),sql_c_type, field, fieldsize, &result->values[field_ind].vallen);
  1878. if (rc == SQL_ERROR) {
  1879. odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
  1880. efree(field);
  1881. RETURN_FALSE;
  1882. }
  1883. if (result->values[field_ind].vallen == SQL_NULL_DATA) {
  1884. efree(field);
  1885. RETURN_NULL();
  1886. }
  1887. /* chop the trailing \0 by outputing only 4095 bytes */
  1888. PHPWRITE(field,(rc == SQL_SUCCESS_WITH_INFO) ? 4095 : result->values[field_ind].vallen);
  1889. if (rc == SQL_SUCCESS) { /* no more data avail */
  1890. efree(field);
  1891. RETURN_TRUE;
  1892. }
  1893. }
  1894. RETURN_TRUE;
  1895. }
  1896. /* }}} */
  1897. /* {{{ proto int odbc_result_all(resource result_id [, string format])
  1898. Print result as HTML table */
  1899. PHP_FUNCTION(odbc_result_all)
  1900. {
  1901. char *buf = NULL;
  1902. odbc_result *result;
  1903. RETCODE rc;
  1904. zval *pv_res;
  1905. char *pv_format = NULL;
  1906. int i, pv_format_len = 0;
  1907. SQLSMALLINT sql_c_type;
  1908. #ifdef HAVE_SQL_EXTENDED_FETCH
  1909. SQLULEN crow;
  1910. SQLUSMALLINT RowStatus[1];
  1911. #endif
  1912. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s", &pv_res, &pv_format, &pv_format_len) == FAILURE) {
  1913. return;
  1914. }
  1915. ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
  1916. if (result->numcols == 0) {
  1917. php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
  1918. RETURN_FALSE;
  1919. }
  1920. #ifdef HAVE_SQL_EXTENDED_FETCH
  1921. if (result->fetch_abs)
  1922. rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
  1923. else
  1924. #endif
  1925. rc = SQLFetch(result->stmt);
  1926. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  1927. php_printf("<h2>No rows found</h2>\n");
  1928. RETURN_LONG(0);
  1929. }
  1930. /* Start table tag */
  1931. if (ZEND_NUM_ARGS() == 1) {
  1932. php_printf("<table><tr>");
  1933. } else {
  1934. php_printf("<table %s ><tr>", pv_format);
  1935. }
  1936. for (i = 0; i < result->numcols; i++) {
  1937. php_printf("<th>%s</th>", result->values[i].name);
  1938. }
  1939. php_printf("</tr>\n");
  1940. while(rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) {
  1941. result->fetched++;
  1942. php_printf("<tr>");
  1943. for(i = 0; i < result->numcols; i++) {
  1944. sql_c_type = SQL_C_CHAR;
  1945. switch(result->values[i].coltype) {
  1946. case SQL_BINARY:
  1947. case SQL_VARBINARY:
  1948. case SQL_LONGVARBINARY:
  1949. if (result->binmode <= 0) {
  1950. php_printf("<td>Not printable</td>");
  1951. break;
  1952. }
  1953. if (result->binmode <= 1) sql_c_type = SQL_C_BINARY;
  1954. case SQL_LONGVARCHAR:
  1955. if (IS_SQL_LONG(result->values[i].coltype) &&
  1956. result->longreadlen <= 0) {
  1957. php_printf("<td>Not printable</td>");
  1958. break;
  1959. }
  1960. if (buf == NULL) {
  1961. buf = emalloc(result->longreadlen);
  1962. }
  1963. rc = SQLGetData(result->stmt, (SQLUSMALLINT)(i + 1),sql_c_type, buf, result->longreadlen, &result->values[i].vallen);
  1964. php_printf("<td>");
  1965. if (rc == SQL_ERROR) {
  1966. odbc_sql_error(result->conn_ptr, result->stmt, "SQLGetData");
  1967. php_printf("</td></tr></table>");
  1968. efree(buf);
  1969. RETURN_FALSE;
  1970. }
  1971. if (rc == SQL_SUCCESS_WITH_INFO) {
  1972. PHPWRITE(buf, result->longreadlen);
  1973. } else if (result->values[i].vallen == SQL_NULL_DATA) {
  1974. php_printf("<td>NULL</td>");
  1975. break;
  1976. } else {
  1977. PHPWRITE(buf, result->values[i].vallen);
  1978. }
  1979. php_printf("</td>");
  1980. break;
  1981. default:
  1982. if (result->values[i].vallen == SQL_NULL_DATA) {
  1983. php_printf("<td>NULL</td>");
  1984. } else {
  1985. php_printf("<td>%s</td>", result->values[i].value);
  1986. }
  1987. break;
  1988. }
  1989. }
  1990. php_printf("</tr>\n");
  1991. #ifdef HAVE_SQL_EXTENDED_FETCH
  1992. if (result->fetch_abs)
  1993. rc = SQLExtendedFetch(result->stmt,SQL_FETCH_NEXT,1,&crow,RowStatus);
  1994. else
  1995. #endif
  1996. rc = SQLFetch(result->stmt);
  1997. }
  1998. php_printf("</table>\n");
  1999. if (buf) efree(buf);
  2000. RETURN_LONG(result->fetched);
  2001. }
  2002. /* }}} */
  2003. /* {{{ proto bool odbc_free_result(resource result_id)
  2004. Free resources associated with a result */
  2005. PHP_FUNCTION(odbc_free_result)
  2006. {
  2007. zval *pv_res;
  2008. odbc_result *result;
  2009. int i;
  2010. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) {
  2011. return;
  2012. }
  2013. ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
  2014. if (result->values) {
  2015. for (i = 0; i < result->numcols; i++) {
  2016. if (result->values[i].value) {
  2017. efree(result->values[i].value);
  2018. }
  2019. }
  2020. efree(result->values);
  2021. result->values = NULL;
  2022. }
  2023. zend_list_delete(Z_LVAL_P(pv_res));
  2024. RETURN_TRUE;
  2025. }
  2026. /* }}} */
  2027. /* {{{ proto resource odbc_connect(string DSN, string user, string password [, int cursor_option])
  2028. Connect to a datasource */
  2029. PHP_FUNCTION(odbc_connect)
  2030. {
  2031. odbc_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  2032. }
  2033. /* }}} */
  2034. /* {{{ proto resource odbc_pconnect(string DSN, string user, string password [, int cursor_option])
  2035. Establish a persistent connection to a datasource */
  2036. PHP_FUNCTION(odbc_pconnect)
  2037. {
  2038. odbc_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  2039. }
  2040. /* }}} */
  2041. /* {{{ odbc_sqlconnect */
  2042. int odbc_sqlconnect(odbc_connection **conn, char *db, char *uid, char *pwd, int cur_opt, int persistent TSRMLS_DC)
  2043. {
  2044. RETCODE rc;
  2045. *conn = (odbc_connection *)pemalloc(sizeof(odbc_connection), persistent);
  2046. (*conn)->persistent = persistent;
  2047. SQLAllocEnv(&((*conn)->henv));
  2048. SQLAllocConnect((*conn)->henv, &((*conn)->hdbc));
  2049. #if defined(HAVE_SOLID) || defined(HAVE_SOLID_30)
  2050. SQLSetConnectOption((*conn)->hdbc, SQL_TRANSLATE_OPTION,
  2051. SQL_SOLID_XLATOPT_NOCNV);
  2052. #endif
  2053. #ifdef HAVE_ODBC_ROUTER
  2054. {
  2055. #define CONNSTRSIZE 2048
  2056. char *lpszConnStr = emalloc(CONNSTRSIZE);
  2057. if (lpszConnStr && db) {
  2058. short cbszConnStr;
  2059. if (strstr(db, ";")) {
  2060. /* the caller has apparently passed a connection-string */
  2061. if (strstr(db, "uid") || strstr(db, "UID")) {
  2062. uid = NULL;
  2063. }
  2064. if (strstr(db, "pwd") || strstr(db, "PWD")) {
  2065. pwd = NULL;
  2066. }
  2067. strlcpy( lpszConnStr, db, CONNSTRSIZE);
  2068. }
  2069. else {
  2070. strcpy(lpszConnStr, "DSN=");
  2071. strlcat(lpszConnStr, db, CONNSTRSIZE);
  2072. }
  2073. if (uid) {
  2074. if (uid[0]) {
  2075. strlcat(lpszConnStr, ";UID=", CONNSTRSIZE);
  2076. strlcat(lpszConnStr, uid, CONNSTRSIZE);
  2077. strlcat(lpszConnStr, ";", CONNSTRSIZE);
  2078. }
  2079. if (pwd) {
  2080. if (pwd[0]) {
  2081. strlcat(lpszConnStr, "PWD=", CONNSTRSIZE);
  2082. strlcat(lpszConnStr, pwd, CONNSTRSIZE);
  2083. strlcat(lpszConnStr, ";", CONNSTRSIZE);
  2084. }
  2085. }
  2086. }
  2087. rc = SQLDriverConnect((*conn)->hdbc, NULL, lpszConnStr, SQL_NTS, lpszConnStr, CONNSTRSIZE, &cbszConnStr, SQL_DRIVER_NOPROMPT);
  2088. efree(lpszConnStr);
  2089. }
  2090. }
  2091. #else
  2092. #ifdef HAVE_OPENLINK
  2093. {
  2094. char dsnbuf[1024];
  2095. short dsnbuflen;
  2096. rc = SQLDriverConnect((*conn)->hdbc, NULL, db, SQL_NTS, dsnbuf, sizeof(dsnbuf) - 1, &dsnbuflen, SQL_DRIVER_NOPROMPT);
  2097. }
  2098. #else
  2099. if (cur_opt != SQL_CUR_DEFAULT) {
  2100. rc = SQLSetConnectOption((*conn)->hdbc, SQL_ODBC_CURSORS, cur_opt);
  2101. if (rc != SQL_SUCCESS) { /* && rc != SQL_SUCCESS_WITH_INFO ? */
  2102. odbc_sql_error(*conn, SQL_NULL_HSTMT, "SQLSetConnectOption");
  2103. SQLFreeConnect((*conn)->hdbc);
  2104. pefree(*conn, persistent);
  2105. return FALSE;
  2106. }
  2107. }
  2108. /* Possible fix for bug #10250
  2109. * Needs testing on UnixODBC < 2.0.5 though. */
  2110. #if defined(HAVE_EMPRESS) || defined(HAVE_UNIXODBC) || defined(PHP_WIN32) || defined (HAVE_IODBC)
  2111. /* * Uncomment the line above, and comment line below to fully test
  2112. * #ifdef HAVE_EMPRESS */
  2113. {
  2114. int direct = 0;
  2115. char dsnbuf[1024];
  2116. short dsnbuflen;
  2117. char *ldb = 0;
  2118. int ldb_len = 0;
  2119. if (strstr((char*)db, ";")) {
  2120. direct = 1;
  2121. if (uid && !strstr ((char*)db, "uid") && !strstr((char*)db, "UID")) {
  2122. spprintf(&ldb, 0, "%s;UID=%s;PWD=%s", db, uid, pwd);
  2123. } else {
  2124. ldb_len = strlen(db)+1;
  2125. ldb = (char*) emalloc(ldb_len);
  2126. memcpy(ldb, db, ldb_len);
  2127. }
  2128. }
  2129. if (direct) {
  2130. rc = SQLDriverConnect((*conn)->hdbc, NULL, ldb, strlen(ldb), dsnbuf, sizeof(dsnbuf) - 1, &dsnbuflen, SQL_DRIVER_NOPROMPT);
  2131. } else {
  2132. rc = SQLConnect((*conn)->hdbc, db, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS);
  2133. }
  2134. if (ldb) {
  2135. efree(ldb);
  2136. }
  2137. }
  2138. #else
  2139. rc = SQLConnect((*conn)->hdbc, db, SQL_NTS, uid, SQL_NTS, pwd, SQL_NTS);
  2140. #endif
  2141. #endif
  2142. #endif
  2143. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  2144. odbc_sql_error(*conn, SQL_NULL_HSTMT, "SQLConnect");
  2145. SQLFreeConnect((*conn)->hdbc);
  2146. pefree((*conn), persistent);
  2147. return FALSE;
  2148. }
  2149. /* (*conn)->open = 1;*/
  2150. return TRUE;
  2151. }
  2152. /* }}} */
  2153. /* Persistent connections: two list-types le_pconn, le_conn and a plist
  2154. * where hashed connection info is stored together with index pointer to
  2155. * the actual link of type le_pconn in the list. Only persistent
  2156. * connections get hashed up. Normal connections use existing pconnections.
  2157. * Maybe this has to change with regard to transactions on pconnections?
  2158. * Possibly set autocommit to on on request shutdown.
  2159. *
  2160. * We do have to hash non-persistent connections, and reuse connections.
  2161. * In the case where two connects were being made, without closing the first
  2162. * connect, access violations were occuring. This is because some of the
  2163. * "globals" in this module should actualy be per-connection variables. I
  2164. * simply fixed things to get them working for now. Shane
  2165. */
  2166. /* {{{ odbc_do_connect */
  2167. void odbc_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
  2168. {
  2169. char *db, *uid, *pwd;
  2170. int db_len, uid_len, pwd_len;
  2171. long pv_opt = SQL_CUR_DEFAULT;
  2172. odbc_connection *db_conn;
  2173. char *hashed_details;
  2174. int hashed_len, cur_opt;
  2175. /* Now an optional 4th parameter specifying the cursor type
  2176. * defaulting to the cursors default
  2177. */
  2178. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|l", &db, &db_len, &uid, &uid_len, &pwd, &pwd_len, &pv_opt) == FAILURE) {
  2179. return;
  2180. }
  2181. cur_opt = pv_opt;
  2182. if (ZEND_NUM_ARGS() > 3) {
  2183. /* Confirm the cur_opt range */
  2184. if (! (cur_opt == SQL_CUR_USE_IF_NEEDED ||
  2185. cur_opt == SQL_CUR_USE_ODBC ||
  2186. cur_opt == SQL_CUR_USE_DRIVER ||
  2187. cur_opt == SQL_CUR_DEFAULT) ) {
  2188. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid Cursor type (%d)", cur_opt);
  2189. RETURN_FALSE;
  2190. }
  2191. }
  2192. if (ODBCG(allow_persistent) <= 0) {
  2193. persistent = 0;
  2194. }
  2195. hashed_len = spprintf(&hashed_details, 0, "%s_%s_%s_%s_%d", ODBC_TYPE, db, uid, pwd, cur_opt);
  2196. /* FIXME the idea of checking to see if our connection is already persistent
  2197. is good, but it adds a lot of overhead to non-persistent connections. We
  2198. should look and see if we can fix that somehow */
  2199. /* try to find if we already have this link in our persistent list,
  2200. * no matter if it is to be persistent or not
  2201. */
  2202. try_and_get_another_connection:
  2203. if (persistent) {
  2204. zend_rsrc_list_entry *le;
  2205. /* the link is not in the persistent list */
  2206. if (zend_hash_find(&EG(persistent_list), hashed_details, hashed_len + 1, (void **) &le) == FAILURE) {
  2207. zend_rsrc_list_entry new_le;
  2208. if (ODBCG(max_links) != -1 && ODBCG(num_links) >= ODBCG(max_links)) {
  2209. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", ODBCG(num_links));
  2210. efree(hashed_details);
  2211. RETURN_FALSE;
  2212. }
  2213. if (ODBCG(max_persistent) != -1 && ODBCG(num_persistent) >= ODBCG(max_persistent)) {
  2214. php_error_docref(NULL TSRMLS_CC, E_WARNING,"Too many open persistent links (%ld)", ODBCG(num_persistent));
  2215. efree(hashed_details);
  2216. RETURN_FALSE;
  2217. }
  2218. if (!odbc_sqlconnect(&db_conn, db, uid, pwd, cur_opt, 1 TSRMLS_CC)) {
  2219. efree(hashed_details);
  2220. RETURN_FALSE;
  2221. }
  2222. Z_TYPE(new_le) = le_pconn;
  2223. new_le.ptr = db_conn;
  2224. if (zend_hash_update(&EG(persistent_list), hashed_details, hashed_len + 1, &new_le,
  2225. sizeof(zend_rsrc_list_entry), NULL) == FAILURE) {
  2226. free(db_conn);
  2227. efree(hashed_details);
  2228. RETURN_FALSE;
  2229. }
  2230. ODBCG(num_persistent)++;
  2231. ODBCG(num_links)++;
  2232. db_conn->id = ZEND_REGISTER_RESOURCE(return_value, db_conn, le_pconn);
  2233. } else { /* found connection */
  2234. if (Z_TYPE_P(le) != le_pconn) {
  2235. RETURN_FALSE;
  2236. }
  2237. /*
  2238. * check to see if the connection is still valid
  2239. */
  2240. db_conn = (odbc_connection *)le->ptr;
  2241. /*
  2242. * check to see if the connection is still in place (lurcher)
  2243. */
  2244. if(ODBCG(check_persistent)){
  2245. RETCODE ret;
  2246. UCHAR d_name[32];
  2247. SQLSMALLINT len;
  2248. ret = SQLGetInfo(db_conn->hdbc,
  2249. SQL_DATA_SOURCE_READ_ONLY,
  2250. d_name, sizeof(d_name), &len);
  2251. if(ret != SQL_SUCCESS || len == 0) {
  2252. zend_hash_del(&EG(persistent_list), hashed_details, hashed_len + 1);
  2253. /* Commented out to fix a possible double closure error
  2254. * when working with persistent connections as submitted by
  2255. * bug #15758
  2256. *
  2257. * safe_odbc_disconnect(db_conn->hdbc);
  2258. * SQLFreeConnect(db_conn->hdbc);
  2259. */
  2260. goto try_and_get_another_connection;
  2261. }
  2262. }
  2263. }
  2264. db_conn->id = ZEND_REGISTER_RESOURCE(return_value, db_conn, le_pconn);
  2265. } else { /* non persistent */
  2266. zend_rsrc_list_entry *index_ptr, new_index_ptr;
  2267. if (zend_hash_find(&EG(regular_list), hashed_details, hashed_len + 1, (void **) &index_ptr) == SUCCESS) {
  2268. int type, conn_id;
  2269. void *ptr;
  2270. if (Z_TYPE_P(index_ptr) != le_index_ptr) {
  2271. RETURN_FALSE;
  2272. }
  2273. conn_id = (int)index_ptr->ptr;
  2274. ptr = zend_list_find(conn_id, &type); /* check if the connection is still there */
  2275. if (ptr && (type == le_conn || type == le_pconn)) {
  2276. zend_list_addref(conn_id);
  2277. Z_LVAL_P(return_value) = conn_id;
  2278. Z_TYPE_P(return_value) = IS_RESOURCE;
  2279. efree(hashed_details);
  2280. return;
  2281. } else {
  2282. zend_hash_del(&EG(regular_list), hashed_details, hashed_len + 1);
  2283. }
  2284. }
  2285. if (ODBCG(max_links) != -1 && ODBCG(num_links) >= ODBCG(max_links)) {
  2286. php_error_docref(NULL TSRMLS_CC, E_WARNING,"Too many open connections (%ld)",ODBCG(num_links));
  2287. efree(hashed_details);
  2288. RETURN_FALSE;
  2289. }
  2290. if (!odbc_sqlconnect(&db_conn, db, uid, pwd, cur_opt, 0 TSRMLS_CC)) {
  2291. efree(hashed_details);
  2292. RETURN_FALSE;
  2293. }
  2294. db_conn->id = ZEND_REGISTER_RESOURCE(return_value, db_conn, le_conn);
  2295. new_index_ptr.ptr = (void *) Z_LVAL_P(return_value);
  2296. Z_TYPE(new_index_ptr) = le_index_ptr;
  2297. if (zend_hash_update(&EG(regular_list), hashed_details, hashed_len + 1, (void *) &new_index_ptr,
  2298. sizeof(zend_rsrc_list_entry), NULL) == FAILURE) {
  2299. efree(hashed_details);
  2300. RETURN_FALSE;
  2301. /* XXX Free Connection */
  2302. }
  2303. ODBCG(num_links)++;
  2304. }
  2305. efree(hashed_details);
  2306. }
  2307. /* }}} */
  2308. /* {{{ proto void odbc_close(resource connection_id)
  2309. Close an ODBC connection */
  2310. PHP_FUNCTION(odbc_close)
  2311. {
  2312. zval *pv_conn;
  2313. void *ptr;
  2314. odbc_connection *conn;
  2315. odbc_result *res;
  2316. int nument;
  2317. int i;
  2318. int type;
  2319. int is_pconn = 0;
  2320. int found_resource_type = le_conn;
  2321. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_conn) == FAILURE) {
  2322. return;
  2323. }
  2324. conn = (odbc_connection *) zend_fetch_resource(&pv_conn TSRMLS_CC, -1, "ODBC-Link", &found_resource_type, 2, le_conn, le_pconn);
  2325. if (found_resource_type==le_pconn) {
  2326. is_pconn = 1;
  2327. }
  2328. nument = zend_hash_next_free_element(&EG(regular_list));
  2329. for(i = 1; i < nument; i++){
  2330. ptr = zend_list_find(i, &type);
  2331. if(ptr && (type == le_result)){
  2332. res = (odbc_result *)ptr;
  2333. if(res->conn_ptr == conn){
  2334. zend_list_delete(i);
  2335. }
  2336. }
  2337. }
  2338. zend_list_delete(Z_LVAL_P(pv_conn));
  2339. if(is_pconn){
  2340. zend_hash_apply_with_argument(&EG(persistent_list), (apply_func_arg_t) _close_pconn_with_id, (void *) &(Z_LVAL_P(pv_conn)) TSRMLS_CC);
  2341. }
  2342. }
  2343. /* }}} */
  2344. /* {{{ proto int odbc_num_rows(resource result_id)
  2345. Get number of rows in a result */
  2346. PHP_FUNCTION(odbc_num_rows)
  2347. {
  2348. odbc_result *result;
  2349. SQLLEN rows;
  2350. zval *pv_res;
  2351. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) {
  2352. return;
  2353. }
  2354. ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
  2355. SQLRowCount(result->stmt, &rows);
  2356. RETURN_LONG(rows);
  2357. }
  2358. /* }}} */
  2359. #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30)
  2360. /* {{{ proto bool odbc_next_result(resource result_id)
  2361. Checks if multiple results are avaiable */
  2362. PHP_FUNCTION(odbc_next_result)
  2363. {
  2364. odbc_result *result;
  2365. zval *pv_res;
  2366. int rc, i;
  2367. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) {
  2368. return;
  2369. }
  2370. ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
  2371. if (result->values) {
  2372. for(i = 0; i < result->numcols; i++) {
  2373. if (result->values[i].value) {
  2374. efree(result->values[i].value);
  2375. }
  2376. }
  2377. efree(result->values);
  2378. result->values = NULL;
  2379. }
  2380. result->fetched = 0;
  2381. rc = SQLMoreResults(result->stmt);
  2382. if (rc == SQL_SUCCESS_WITH_INFO || rc == SQL_SUCCESS) {
  2383. rc = SQLFreeStmt(result->stmt, SQL_UNBIND);
  2384. SQLNumParams(result->stmt, &(result->numparams));
  2385. SQLNumResultCols(result->stmt, &(result->numcols));
  2386. if (result->numcols > 0) {
  2387. if (!odbc_bindcols(result TSRMLS_CC)) {
  2388. efree(result);
  2389. RETVAL_FALSE;
  2390. }
  2391. } else {
  2392. result->values = NULL;
  2393. }
  2394. RETURN_TRUE;
  2395. } else if (rc == SQL_NO_DATA_FOUND) {
  2396. RETURN_FALSE;
  2397. } else {
  2398. odbc_sql_error(result->conn_ptr, result->stmt, "SQLMoreResults");
  2399. RETURN_FALSE;
  2400. }
  2401. }
  2402. /* }}} */
  2403. #endif
  2404. /* {{{ proto int odbc_num_fields(resource result_id)
  2405. Get number of columns in a result */
  2406. PHP_FUNCTION(odbc_num_fields)
  2407. {
  2408. odbc_result *result;
  2409. zval *pv_res;
  2410. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pv_res) == FAILURE) {
  2411. return;
  2412. }
  2413. ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
  2414. RETURN_LONG(result->numcols);
  2415. }
  2416. /* }}} */
  2417. /* {{{ proto string odbc_field_name(resource result_id, int field_number)
  2418. Get a column name */
  2419. PHP_FUNCTION(odbc_field_name)
  2420. {
  2421. odbc_result *result;
  2422. zval *pv_res;
  2423. long pv_num;
  2424. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &pv_res, &pv_num) == FAILURE) {
  2425. return;
  2426. }
  2427. ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
  2428. if (result->numcols == 0) {
  2429. php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
  2430. RETURN_FALSE;
  2431. }
  2432. if (pv_num > result->numcols) {
  2433. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field index larger than number of fields");
  2434. RETURN_FALSE;
  2435. }
  2436. if (pv_num < 1) {
  2437. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field numbering starts at 1");
  2438. RETURN_FALSE;
  2439. }
  2440. RETURN_STRING(result->values[pv_num - 1].name, 1);
  2441. }
  2442. /* }}} */
  2443. /* {{{ proto string odbc_field_type(resource result_id, int field_number)
  2444. Get the datatype of a column */
  2445. PHP_FUNCTION(odbc_field_type)
  2446. {
  2447. odbc_result *result;
  2448. char tmp[32];
  2449. SQLSMALLINT tmplen;
  2450. zval *pv_res;
  2451. long pv_num;
  2452. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &pv_res, &pv_num) == FAILURE) {
  2453. return;
  2454. }
  2455. ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
  2456. if (result->numcols == 0) {
  2457. php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
  2458. RETURN_FALSE;
  2459. }
  2460. if (pv_num > result->numcols) {
  2461. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field index larger than number of fields");
  2462. RETURN_FALSE;
  2463. }
  2464. if (pv_num < 1) {
  2465. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field numbering starts at 1");
  2466. RETURN_FALSE;
  2467. }
  2468. SQLColAttributes(result->stmt, (SQLUSMALLINT)pv_num, SQL_COLUMN_TYPE_NAME, tmp, 31, &tmplen, NULL);
  2469. RETURN_STRING(tmp,1)
  2470. }
  2471. /* }}} */
  2472. /* {{{ proto int odbc_field_len(resource result_id, int field_number)
  2473. Get the length (precision) of a column */
  2474. PHP_FUNCTION(odbc_field_len)
  2475. {
  2476. odbc_column_lengths(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  2477. }
  2478. /* }}} */
  2479. /* {{{ proto int odbc_field_scale(resource result_id, int field_number)
  2480. Get the scale of a column */
  2481. PHP_FUNCTION(odbc_field_scale)
  2482. {
  2483. odbc_column_lengths(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  2484. }
  2485. /* }}} */
  2486. /* {{{ proto int odbc_field_num(resource result_id, string field_name)
  2487. Return column number */
  2488. PHP_FUNCTION(odbc_field_num)
  2489. {
  2490. char *fname;
  2491. int i, field_ind, fname_len;
  2492. odbc_result *result;
  2493. zval *pv_res;
  2494. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pv_res, &fname, &fname_len) == FAILURE) {
  2495. return;
  2496. }
  2497. ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_res, -1, "ODBC result", le_result);
  2498. if (result->numcols == 0) {
  2499. php_error_docref(NULL TSRMLS_CC, E_WARNING, "No tuples available at this result index");
  2500. RETURN_FALSE;
  2501. }
  2502. field_ind = -1;
  2503. for(i = 0; i < result->numcols; i++) {
  2504. if (strcasecmp(result->values[i].name, fname) == 0) {
  2505. field_ind = i + 1;
  2506. }
  2507. }
  2508. if (field_ind == -1) {
  2509. RETURN_FALSE;
  2510. }
  2511. RETURN_LONG(field_ind);
  2512. }
  2513. /* }}} */
  2514. /* {{{ proto mixed odbc_autocommit(resource connection_id [, int OnOff])
  2515. Toggle autocommit mode or get status */
  2516. /* There can be problems with pconnections!*/
  2517. PHP_FUNCTION(odbc_autocommit)
  2518. {
  2519. odbc_connection *conn;
  2520. RETCODE rc;
  2521. zval *pv_conn;
  2522. long pv_onoff = 0;
  2523. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &pv_conn, &pv_onoff) == FAILURE) {
  2524. return;
  2525. }
  2526. ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
  2527. if (ZEND_NUM_ARGS() > 1) {
  2528. rc = SQLSetConnectOption(conn->hdbc, SQL_AUTOCOMMIT, (pv_onoff) ? SQL_AUTOCOMMIT_ON : SQL_AUTOCOMMIT_OFF);
  2529. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  2530. odbc_sql_error(conn, SQL_NULL_HSTMT, "Set autocommit");
  2531. RETURN_FALSE;
  2532. }
  2533. RETVAL_TRUE;
  2534. } else {
  2535. SQLINTEGER status;
  2536. rc = SQLGetConnectOption(conn->hdbc, SQL_AUTOCOMMIT, (PTR)&status);
  2537. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  2538. odbc_sql_error(conn, SQL_NULL_HSTMT, "Get commit status");
  2539. RETURN_FALSE;
  2540. }
  2541. RETVAL_LONG((long)status);
  2542. }
  2543. }
  2544. /* }}} */
  2545. /* {{{ proto bool odbc_commit(resource connection_id)
  2546. Commit an ODBC transaction */
  2547. PHP_FUNCTION(odbc_commit)
  2548. {
  2549. odbc_transact(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  2550. }
  2551. /* }}} */
  2552. /* {{{ proto bool odbc_rollback(resource connection_id)
  2553. Rollback a transaction */
  2554. PHP_FUNCTION(odbc_rollback)
  2555. {
  2556. odbc_transact(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  2557. }
  2558. /* }}} */
  2559. /* {{{ php_odbc_lasterror */
  2560. static void php_odbc_lasterror(INTERNAL_FUNCTION_PARAMETERS, int mode)
  2561. {
  2562. odbc_connection *conn;
  2563. zval *pv_handle;
  2564. char *ptr;
  2565. int len;
  2566. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|r", &pv_handle) == FAILURE) {
  2567. return;
  2568. }
  2569. if (mode == 0) { /* last state */
  2570. len = 6;
  2571. } else { /* last error message */
  2572. len = SQL_MAX_MESSAGE_LENGTH;
  2573. }
  2574. if (ZEND_NUM_ARGS() == 1) {
  2575. ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_handle, -1, "ODBC-Link", le_conn, le_pconn);
  2576. ptr = ecalloc(len + 1, 1);
  2577. if (mode == 0) {
  2578. strlcpy(ptr, conn->laststate, len+1);
  2579. } else {
  2580. strlcpy(ptr, conn->lasterrormsg, len+1);
  2581. }
  2582. } else {
  2583. ptr = ecalloc(len + 1, 1);
  2584. if (mode == 0) {
  2585. strlcpy(ptr, ODBCG(laststate), len+1);
  2586. } else {
  2587. strlcpy(ptr, ODBCG(lasterrormsg), len+1);
  2588. }
  2589. }
  2590. RETVAL_STRING(ptr, 0);
  2591. }
  2592. /* }}} */
  2593. /* {{{ proto string odbc_error([resource connection_id])
  2594. Get the last error code */
  2595. PHP_FUNCTION(odbc_error)
  2596. {
  2597. php_odbc_lasterror(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
  2598. }
  2599. /* }}} */
  2600. /* {{{ proto string odbc_errormsg([resource connection_id])
  2601. Get the last error message */
  2602. PHP_FUNCTION(odbc_errormsg)
  2603. {
  2604. php_odbc_lasterror(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
  2605. }
  2606. /* }}} */
  2607. /* {{{ proto bool odbc_setoption(resource conn_id|result_id, int which, int option, int value)
  2608. Sets connection or statement options */
  2609. /* This one has to be used carefully. We can't allow to set connection options for
  2610. persistent connections. I think that SetStmtOption is of little use, since most
  2611. of those can only be specified before preparing/executing statements.
  2612. On the other hand, they can be made connection wide default through SetConnectOption
  2613. - but will be overidden by calls to SetStmtOption() in odbc_prepare/odbc_do
  2614. */
  2615. PHP_FUNCTION(odbc_setoption)
  2616. {
  2617. odbc_connection *conn;
  2618. odbc_result *result;
  2619. RETCODE rc;
  2620. zval *pv_handle;
  2621. long pv_which, pv_opt, pv_val;
  2622. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlll", &pv_handle, &pv_which, &pv_opt, &pv_val) == FAILURE) {
  2623. return;
  2624. }
  2625. switch (pv_which) {
  2626. case 1: /* SQLSetConnectOption */
  2627. ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_handle, -1, "ODBC-Link", le_conn, le_pconn);
  2628. if (conn->persistent) {
  2629. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set option for persistent connection");
  2630. RETURN_FALSE;
  2631. }
  2632. rc = SQLSetConnectOption(conn->hdbc, (unsigned short) pv_opt, pv_val);
  2633. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  2634. odbc_sql_error(conn, SQL_NULL_HSTMT, "SetConnectOption");
  2635. RETURN_FALSE;
  2636. }
  2637. break;
  2638. case 2: /* SQLSetStmtOption */
  2639. ZEND_FETCH_RESOURCE(result, odbc_result *, &pv_handle, -1, "ODBC result", le_result);
  2640. rc = SQLSetStmtOption(result->stmt, (unsigned short) pv_opt, pv_val);
  2641. if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
  2642. odbc_sql_error(result->conn_ptr, result->stmt, "SetStmtOption");
  2643. RETURN_FALSE;
  2644. }
  2645. break;
  2646. default:
  2647. php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown option type");
  2648. RETURN_FALSE;
  2649. break;
  2650. }
  2651. RETURN_TRUE;
  2652. }
  2653. /* }}} */
  2654. /*
  2655. * metadata functions
  2656. */
  2657. /* {{{ proto resource odbc_tables(resource connection_id [, string qualifier [, string owner [, string name [, string table_types]]]])
  2658. Call the SQLTables function */
  2659. PHP_FUNCTION(odbc_tables)
  2660. {
  2661. zval *pv_conn;
  2662. odbc_result *result = NULL;
  2663. odbc_connection *conn;
  2664. char *cat = NULL, *schema = NULL, *table = NULL, *type = NULL;
  2665. int cat_len = 0, schema_len = 0, table_len = 0, type_len = 0;
  2666. RETCODE rc;
  2667. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!sss", &pv_conn, &cat, &cat_len, &schema, &schema_len,
  2668. &table, &table_len, &type, &type_len) == FAILURE) {
  2669. return;
  2670. }
  2671. ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
  2672. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  2673. rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
  2674. if (rc == SQL_INVALID_HANDLE) {
  2675. efree(result);
  2676. php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  2677. RETURN_FALSE;
  2678. }
  2679. if (rc == SQL_ERROR) {
  2680. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  2681. efree(result);
  2682. RETURN_FALSE;
  2683. }
  2684. /* This hack is needed to access table information in Access databases (fmk) */
  2685. if (table && table_len && schema && schema_len == 0) {
  2686. schema = NULL;
  2687. }
  2688. rc = SQLTables(result->stmt,
  2689. cat, SAFE_SQL_NTS(cat),
  2690. schema, SAFE_SQL_NTS(schema),
  2691. table, SAFE_SQL_NTS(table),
  2692. type, SAFE_SQL_NTS(type));
  2693. if (rc == SQL_ERROR) {
  2694. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLTables");
  2695. efree(result);
  2696. RETURN_FALSE;
  2697. }
  2698. result->numparams = 0;
  2699. SQLNumResultCols(result->stmt, &(result->numcols));
  2700. if (result->numcols > 0) {
  2701. if (!odbc_bindcols(result TSRMLS_CC)) {
  2702. efree(result);
  2703. RETURN_FALSE;
  2704. }
  2705. } else {
  2706. result->values = NULL;
  2707. }
  2708. result->conn_ptr = conn;
  2709. result->fetched = 0;
  2710. ZEND_REGISTER_RESOURCE(return_value, result, le_result);
  2711. }
  2712. /* }}} */
  2713. /* {{{ proto resource odbc_columns(resource connection_id [, string qualifier [, string owner [, string table_name [, string column_name]]]])
  2714. Returns a result identifier that can be used to fetch a list of column names in specified tables */
  2715. PHP_FUNCTION(odbc_columns)
  2716. {
  2717. zval *pv_conn;
  2718. odbc_result *result = NULL;
  2719. odbc_connection *conn;
  2720. char *cat = NULL, *schema = NULL, *table = NULL, *column = NULL;
  2721. int cat_len = 0, schema_len = 0, table_len = 0, column_len = 0;
  2722. RETCODE rc;
  2723. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!sss", &pv_conn, &cat, &cat_len, &schema, &schema_len,
  2724. &table, &table_len, &column, &column_len) == FAILURE) {
  2725. return;
  2726. }
  2727. ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
  2728. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  2729. rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
  2730. if (rc == SQL_INVALID_HANDLE) {
  2731. efree(result);
  2732. php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  2733. RETURN_FALSE;
  2734. }
  2735. if (rc == SQL_ERROR) {
  2736. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  2737. efree(result);
  2738. RETURN_FALSE;
  2739. }
  2740. /*
  2741. * Needed to make MS Access happy
  2742. */
  2743. if (table && table_len && schema && schema_len == 0) {
  2744. schema = NULL;
  2745. }
  2746. rc = SQLColumns(result->stmt,
  2747. cat, (SQLSMALLINT) cat_len,
  2748. schema, (SQLSMALLINT) schema_len,
  2749. table, (SQLSMALLINT) table_len,
  2750. column, (SQLSMALLINT) column_len);
  2751. if (rc == SQL_ERROR) {
  2752. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLColumns");
  2753. efree(result);
  2754. RETURN_FALSE;
  2755. }
  2756. result->numparams = 0;
  2757. SQLNumResultCols(result->stmt, &(result->numcols));
  2758. if (result->numcols > 0) {
  2759. if (!odbc_bindcols(result TSRMLS_CC)) {
  2760. efree(result);
  2761. RETURN_FALSE;
  2762. }
  2763. } else {
  2764. result->values = NULL;
  2765. }
  2766. result->conn_ptr = conn;
  2767. result->fetched = 0;
  2768. ZEND_REGISTER_RESOURCE(return_value, result, le_result);
  2769. }
  2770. /* }}} */
  2771. #if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) && !defined(HAVE_BIRDSTEP)
  2772. /* {{{ proto resource odbc_columnprivileges(resource connection_id, string catalog, string schema, string table, string column)
  2773. Returns a result identifier that can be used to fetch a list of columns and associated privileges for the specified table */
  2774. PHP_FUNCTION(odbc_columnprivileges)
  2775. {
  2776. zval *pv_conn;
  2777. odbc_result *result = NULL;
  2778. odbc_connection *conn;
  2779. char *cat = NULL, *schema, *table, *column;
  2780. int cat_len = 0, schema_len, table_len, column_len;
  2781. RETCODE rc;
  2782. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!sss", &pv_conn, &cat, &cat_len, &schema, &schema_len,
  2783. &table, &table_len, &column, &column_len) == FAILURE) {
  2784. return;
  2785. }
  2786. ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
  2787. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  2788. rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
  2789. if (rc == SQL_INVALID_HANDLE) {
  2790. efree(result);
  2791. php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  2792. RETURN_FALSE;
  2793. }
  2794. if (rc == SQL_ERROR) {
  2795. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  2796. efree(result);
  2797. RETURN_FALSE;
  2798. }
  2799. rc = SQLColumnPrivileges(result->stmt,
  2800. cat, SAFE_SQL_NTS(cat),
  2801. schema, SAFE_SQL_NTS(schema),
  2802. table, SAFE_SQL_NTS(table),
  2803. column, SAFE_SQL_NTS(column));
  2804. if (rc == SQL_ERROR) {
  2805. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLColumnPrivileges");
  2806. efree(result);
  2807. RETURN_FALSE;
  2808. }
  2809. result->numparams = 0;
  2810. SQLNumResultCols(result->stmt, &(result->numcols));
  2811. if (result->numcols > 0) {
  2812. if (!odbc_bindcols(result TSRMLS_CC)) {
  2813. efree(result);
  2814. RETURN_FALSE;
  2815. }
  2816. } else {
  2817. result->values = NULL;
  2818. }
  2819. result->conn_ptr = conn;
  2820. result->fetched = 0;
  2821. ZEND_REGISTER_RESOURCE(return_value, result, le_result);
  2822. }
  2823. /* }}} */
  2824. #endif /* HAVE_DBMAKER || HAVE_SOLID*/
  2825. #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35)
  2826. /* {{{ proto resource odbc_foreignkeys(resource connection_id, string pk_qualifier, string pk_owner, string pk_table, string fk_qualifier, string fk_owner, string fk_table)
  2827. Returns a result identifier to either a list of foreign keys in the specified table or a list of foreign keys in other tables that refer to the primary key in the specified table */
  2828. PHP_FUNCTION(odbc_foreignkeys)
  2829. {
  2830. zval *pv_conn;
  2831. odbc_result *result = NULL;
  2832. odbc_connection *conn;
  2833. char *pcat = NULL, *pschema, *ptable, *fcat, *fschema, *ftable;
  2834. int pcat_len = 0, pschema_len, ptable_len, fcat_len, fschema_len, ftable_len;
  2835. RETCODE rc;
  2836. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!sssss", &pv_conn, &pcat, &pcat_len, &pschema, &pschema_len,
  2837. &ptable, &ptable_len, &fcat, &fcat_len, &fschema, &fschema_len, &ftable, &ftable_len) == FAILURE) {
  2838. return;
  2839. }
  2840. #if defined(HAVE_DBMAKER) || defined(HAVE_IBMDB2)
  2841. #define EMPTY_TO_NULL(xstr) \
  2842. if ((int)strlen((xstr)) == 0) (xstr) = NULL
  2843. EMPTY_TO_NULL(pcat);
  2844. EMPTY_TO_NULL(pschema);
  2845. EMPTY_TO_NULL(ptable);
  2846. EMPTY_TO_NULL(fcat);
  2847. EMPTY_TO_NULL(fschema);
  2848. EMPTY_TO_NULL(ftable);
  2849. #endif
  2850. ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
  2851. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  2852. rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
  2853. if (rc == SQL_INVALID_HANDLE) {
  2854. efree(result);
  2855. php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  2856. RETURN_FALSE;
  2857. }
  2858. if (rc == SQL_ERROR) {
  2859. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  2860. efree(result);
  2861. RETURN_FALSE;
  2862. }
  2863. rc = SQLForeignKeys(result->stmt,
  2864. pcat, SAFE_SQL_NTS(pcat),
  2865. pschema, SAFE_SQL_NTS(pschema),
  2866. ptable, SAFE_SQL_NTS(ptable),
  2867. fcat, SAFE_SQL_NTS(fcat),
  2868. fschema, SAFE_SQL_NTS(fschema),
  2869. ftable, SAFE_SQL_NTS(ftable) );
  2870. if (rc == SQL_ERROR) {
  2871. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLForeignKeys");
  2872. efree(result);
  2873. RETURN_FALSE;
  2874. }
  2875. result->numparams = 0;
  2876. SQLNumResultCols(result->stmt, &(result->numcols));
  2877. if (result->numcols > 0) {
  2878. if (!odbc_bindcols(result TSRMLS_CC)) {
  2879. efree(result);
  2880. RETURN_FALSE;
  2881. }
  2882. } else {
  2883. result->values = NULL;
  2884. }
  2885. result->conn_ptr = conn;
  2886. result->fetched = 0;
  2887. ZEND_REGISTER_RESOURCE(return_value, result, le_result);
  2888. }
  2889. /* }}} */
  2890. #endif /* HAVE_SOLID */
  2891. /* {{{ proto resource odbc_gettypeinfo(resource connection_id [, int data_type])
  2892. Returns a result identifier containing information about data types supported by the data source */
  2893. PHP_FUNCTION(odbc_gettypeinfo)
  2894. {
  2895. zval *pv_conn;
  2896. long pv_data_type = SQL_ALL_TYPES;
  2897. odbc_result *result = NULL;
  2898. odbc_connection *conn;
  2899. RETCODE rc;
  2900. SQLSMALLINT data_type;
  2901. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &pv_conn, &pv_data_type) == FAILURE) {
  2902. return;
  2903. }
  2904. data_type = (SQLSMALLINT) pv_data_type;
  2905. ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
  2906. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  2907. rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
  2908. if (rc == SQL_INVALID_HANDLE) {
  2909. efree(result);
  2910. php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  2911. RETURN_FALSE;
  2912. }
  2913. if (rc == SQL_ERROR) {
  2914. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  2915. efree(result);
  2916. RETURN_FALSE;
  2917. }
  2918. rc = SQLGetTypeInfo(result->stmt, data_type );
  2919. if (rc == SQL_ERROR) {
  2920. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLGetTypeInfo");
  2921. efree(result);
  2922. RETURN_FALSE;
  2923. }
  2924. result->numparams = 0;
  2925. SQLNumResultCols(result->stmt, &(result->numcols));
  2926. if (result->numcols > 0) {
  2927. if (!odbc_bindcols(result TSRMLS_CC)) {
  2928. efree(result);
  2929. RETURN_FALSE;
  2930. }
  2931. } else {
  2932. result->values = NULL;
  2933. }
  2934. result->conn_ptr = conn;
  2935. result->fetched = 0;
  2936. ZEND_REGISTER_RESOURCE(return_value, result, le_result);
  2937. }
  2938. /* }}} */
  2939. /* {{{ proto resource odbc_primarykeys(resource connection_id, string qualifier, string owner, string table)
  2940. Returns a result identifier listing the column names that comprise the primary key for a table */
  2941. PHP_FUNCTION(odbc_primarykeys)
  2942. {
  2943. zval *pv_conn;
  2944. odbc_result *result = NULL;
  2945. odbc_connection *conn;
  2946. char *cat = NULL, *schema = NULL, *table = NULL;
  2947. int cat_len = 0, schema_len, table_len;
  2948. RETCODE rc;
  2949. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!ss", &pv_conn, &cat, &cat_len, &schema, &schema_len, &table, &table_len) == FAILURE) {
  2950. return;
  2951. }
  2952. ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
  2953. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  2954. rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
  2955. if (rc == SQL_INVALID_HANDLE) {
  2956. efree(result);
  2957. php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  2958. RETURN_FALSE;
  2959. }
  2960. if (rc == SQL_ERROR) {
  2961. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  2962. efree(result);
  2963. RETURN_FALSE;
  2964. }
  2965. rc = SQLPrimaryKeys(result->stmt,
  2966. cat, SAFE_SQL_NTS(cat),
  2967. schema, SAFE_SQL_NTS(schema),
  2968. table, SAFE_SQL_NTS(table) );
  2969. if (rc == SQL_ERROR) {
  2970. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLPrimaryKeys");
  2971. efree(result);
  2972. RETURN_FALSE;
  2973. }
  2974. result->numparams = 0;
  2975. SQLNumResultCols(result->stmt, &(result->numcols));
  2976. if (result->numcols > 0) {
  2977. if (!odbc_bindcols(result TSRMLS_CC)) {
  2978. efree(result);
  2979. RETURN_FALSE;
  2980. }
  2981. } else {
  2982. result->values = NULL;
  2983. }
  2984. result->conn_ptr = conn;
  2985. result->fetched = 0;
  2986. ZEND_REGISTER_RESOURCE(return_value, result, le_result);
  2987. }
  2988. /* }}} */
  2989. #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) && !defined(HAVE_BIRDSTEP)
  2990. /* {{{ proto resource odbc_procedurecolumns(resource connection_id [, string qualifier, string owner, string proc, string column])
  2991. Returns a result identifier containing the list of input and output parameters, as well as the columns that make up the result set for the specified procedures */
  2992. PHP_FUNCTION(odbc_procedurecolumns)
  2993. {
  2994. zval *pv_conn;
  2995. odbc_result *result = NULL;
  2996. odbc_connection *conn;
  2997. char *cat = NULL, *schema = NULL, *proc = NULL, *col = NULL;
  2998. int cat_len = 0, schema_len = 0, proc_len = 0, col_len = 0;
  2999. RETCODE rc;
  3000. if (ZEND_NUM_ARGS() != 1 && ZEND_NUM_ARGS() != 5) {
  3001. WRONG_PARAM_COUNT;
  3002. }
  3003. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!sss", &pv_conn, &cat, &cat_len, &schema, &schema_len,
  3004. &proc, &proc_len, &col, &col_len) == FAILURE) {
  3005. return;
  3006. }
  3007. ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
  3008. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  3009. rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
  3010. if (rc == SQL_INVALID_HANDLE) {
  3011. efree(result);
  3012. php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  3013. RETURN_FALSE;
  3014. }
  3015. if (rc == SQL_ERROR) {
  3016. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  3017. efree(result);
  3018. RETURN_FALSE;
  3019. }
  3020. rc = SQLProcedureColumns(result->stmt,
  3021. cat, SAFE_SQL_NTS(cat),
  3022. schema, SAFE_SQL_NTS(schema),
  3023. proc, SAFE_SQL_NTS(proc),
  3024. col, SAFE_SQL_NTS(col) );
  3025. if (rc == SQL_ERROR) {
  3026. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLProcedureColumns");
  3027. efree(result);
  3028. RETURN_FALSE;
  3029. }
  3030. result->numparams = 0;
  3031. SQLNumResultCols(result->stmt, &(result->numcols));
  3032. if (result->numcols > 0) {
  3033. if (!odbc_bindcols(result TSRMLS_CC)) {
  3034. efree(result);
  3035. RETURN_FALSE;
  3036. }
  3037. } else {
  3038. result->values = NULL;
  3039. }
  3040. result->conn_ptr = conn;
  3041. result->fetched = 0;
  3042. ZEND_REGISTER_RESOURCE(return_value, result, le_result);
  3043. }
  3044. /* }}} */
  3045. #endif /* HAVE_SOLID */
  3046. #if !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35)
  3047. /* {{{ proto resource odbc_procedures(resource connection_id [, string qualifier, string owner, string name])
  3048. Returns a result identifier containg the list of procedure names in a datasource */
  3049. PHP_FUNCTION(odbc_procedures)
  3050. {
  3051. zval *pv_conn;
  3052. odbc_result *result = NULL;
  3053. odbc_connection *conn;
  3054. char *cat = NULL, *schema = NULL, *proc = NULL;
  3055. int cat_len = 0, schema_len = 0, proc_len = 0;
  3056. RETCODE rc;
  3057. if (ZEND_NUM_ARGS() != 1 && ZEND_NUM_ARGS() != 4) {
  3058. WRONG_PARAM_COUNT;
  3059. }
  3060. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|s!ss", &pv_conn, &cat, &cat_len, &schema, &schema_len, &proc, &proc_len) == FAILURE) {
  3061. return;
  3062. }
  3063. ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
  3064. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  3065. rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
  3066. if (rc == SQL_INVALID_HANDLE) {
  3067. efree(result);
  3068. php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  3069. RETURN_FALSE;
  3070. }
  3071. if (rc == SQL_ERROR) {
  3072. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  3073. efree(result);
  3074. RETURN_FALSE;
  3075. }
  3076. rc = SQLProcedures(result->stmt,
  3077. cat, SAFE_SQL_NTS(cat),
  3078. schema, SAFE_SQL_NTS(schema),
  3079. proc, SAFE_SQL_NTS(proc) );
  3080. if (rc == SQL_ERROR) {
  3081. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLProcedures");
  3082. efree(result);
  3083. RETURN_FALSE;
  3084. }
  3085. result->numparams = 0;
  3086. SQLNumResultCols(result->stmt, &(result->numcols));
  3087. if (result->numcols > 0) {
  3088. if (!odbc_bindcols(result TSRMLS_CC)) {
  3089. efree(result);
  3090. RETURN_FALSE;
  3091. }
  3092. } else {
  3093. result->values = NULL;
  3094. }
  3095. result->conn_ptr = conn;
  3096. result->fetched = 0;
  3097. ZEND_REGISTER_RESOURCE(return_value, result, le_result);
  3098. }
  3099. /* }}} */
  3100. #endif /* HAVE_SOLID */
  3101. /* {{{ proto resource odbc_specialcolumns(resource connection_id, int type, string qualifier, string owner, string table, int scope, int nullable)
  3102. Returns a result identifier containing either the optimal set of columns that uniquely identifies a row in the table or columns that are automatically updated when any value in the row is updated by a transaction */
  3103. PHP_FUNCTION(odbc_specialcolumns)
  3104. {
  3105. zval *pv_conn;
  3106. long vtype, vscope, vnullable;
  3107. odbc_result *result = NULL;
  3108. odbc_connection *conn;
  3109. char *cat = NULL, *schema = NULL, *name = NULL;
  3110. int cat_len = 0, schema_len, name_len;
  3111. SQLUSMALLINT type, scope, nullable;
  3112. RETCODE rc;
  3113. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rls!ssll", &pv_conn, &vtype, &cat, &cat_len, &schema, &schema_len,
  3114. &name, &name_len, &vscope, &vnullable) == FAILURE) {
  3115. return;
  3116. }
  3117. type = (SQLUSMALLINT) vtype;
  3118. scope = (SQLUSMALLINT) vscope;
  3119. nullable = (SQLUSMALLINT) vnullable;
  3120. ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
  3121. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  3122. rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
  3123. if (rc == SQL_INVALID_HANDLE) {
  3124. efree(result);
  3125. php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  3126. RETURN_FALSE;
  3127. }
  3128. if (rc == SQL_ERROR) {
  3129. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  3130. efree(result);
  3131. RETURN_FALSE;
  3132. }
  3133. rc = SQLSpecialColumns(result->stmt,
  3134. type,
  3135. cat, SAFE_SQL_NTS(cat),
  3136. schema, SAFE_SQL_NTS(schema),
  3137. name, SAFE_SQL_NTS(name),
  3138. scope,
  3139. nullable);
  3140. if (rc == SQL_ERROR) {
  3141. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLSpecialColumns");
  3142. efree(result);
  3143. RETURN_FALSE;
  3144. }
  3145. result->numparams = 0;
  3146. SQLNumResultCols(result->stmt, &(result->numcols));
  3147. if (result->numcols > 0) {
  3148. if (!odbc_bindcols(result TSRMLS_CC)) {
  3149. efree(result);
  3150. RETURN_FALSE;
  3151. }
  3152. } else {
  3153. result->values = NULL;
  3154. }
  3155. result->conn_ptr = conn;
  3156. result->fetched = 0;
  3157. ZEND_REGISTER_RESOURCE(return_value, result, le_result);
  3158. }
  3159. /* }}} */
  3160. /* {{{ proto resource odbc_statistics(resource connection_id, string qualifier, string owner, string name, int unique, int accuracy)
  3161. Returns a result identifier that contains statistics about a single table and the indexes associated with the table */
  3162. PHP_FUNCTION(odbc_statistics)
  3163. {
  3164. zval *pv_conn;
  3165. long vunique, vreserved;
  3166. odbc_result *result = NULL;
  3167. odbc_connection *conn;
  3168. char *cat = NULL, *schema, *name;
  3169. int cat_len = 0, schema_len, name_len;
  3170. SQLUSMALLINT unique, reserved;
  3171. RETCODE rc;
  3172. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!ssll", &pv_conn, &cat, &cat_len, &schema, &schema_len,
  3173. &name, &name_len, &vunique, &vreserved) == FAILURE) {
  3174. return;
  3175. }
  3176. unique = (SQLUSMALLINT) vunique;
  3177. reserved = (SQLUSMALLINT) vreserved;
  3178. ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
  3179. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  3180. rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
  3181. if (rc == SQL_INVALID_HANDLE) {
  3182. efree(result);
  3183. php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  3184. RETURN_FALSE;
  3185. }
  3186. if (rc == SQL_ERROR) {
  3187. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  3188. efree(result);
  3189. RETURN_FALSE;
  3190. }
  3191. rc = SQLStatistics(result->stmt,
  3192. cat, SAFE_SQL_NTS(cat),
  3193. schema, SAFE_SQL_NTS(schema),
  3194. name, SAFE_SQL_NTS(name),
  3195. unique,
  3196. reserved);
  3197. if (rc == SQL_ERROR) {
  3198. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLStatistics");
  3199. efree(result);
  3200. RETURN_FALSE;
  3201. }
  3202. result->numparams = 0;
  3203. SQLNumResultCols(result->stmt, &(result->numcols));
  3204. if (result->numcols > 0) {
  3205. if (!odbc_bindcols(result TSRMLS_CC)) {
  3206. efree(result);
  3207. RETURN_FALSE;
  3208. }
  3209. } else {
  3210. result->values = NULL;
  3211. }
  3212. result->conn_ptr = conn;
  3213. result->fetched = 0;
  3214. ZEND_REGISTER_RESOURCE(return_value, result, le_result);
  3215. }
  3216. /* }}} */
  3217. #if !defined(HAVE_DBMAKER) && !defined(HAVE_SOLID) && !defined(HAVE_SOLID_30) && !defined(HAVE_SOLID_35) && !defined(HAVE_BIRDSTEP)
  3218. /* {{{ proto resource odbc_tableprivileges(resource connection_id, string qualifier, string owner, string name)
  3219. Returns a result identifier containing a list of tables and the privileges associated with each table */
  3220. PHP_FUNCTION(odbc_tableprivileges)
  3221. {
  3222. zval *pv_conn;
  3223. odbc_result *result = NULL;
  3224. odbc_connection *conn;
  3225. char *cat = NULL, *schema = NULL, *table = NULL;
  3226. int cat_len = 0, schema_len, table_len;
  3227. RETCODE rc;
  3228. if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs!ss", &pv_conn, &cat, &cat_len, &schema, &schema_len, &table, &table_len) == FAILURE) {
  3229. return;
  3230. }
  3231. ZEND_FETCH_RESOURCE2(conn, odbc_connection *, &pv_conn, -1, "ODBC-Link", le_conn, le_pconn);
  3232. result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
  3233. rc = SQLAllocStmt(conn->hdbc, &(result->stmt));
  3234. if (rc == SQL_INVALID_HANDLE) {
  3235. efree(result);
  3236. php_error_docref(NULL TSRMLS_CC, E_WARNING, "SQLAllocStmt error 'Invalid Handle'");
  3237. RETURN_FALSE;
  3238. }
  3239. if (rc == SQL_ERROR) {
  3240. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLAllocStmt");
  3241. efree(result);
  3242. RETURN_FALSE;
  3243. }
  3244. rc = SQLTablePrivileges(result->stmt,
  3245. cat, SAFE_SQL_NTS(cat),
  3246. schema, SAFE_SQL_NTS(schema),
  3247. table, SAFE_SQL_NTS(table));
  3248. if (rc == SQL_ERROR) {
  3249. odbc_sql_error(conn, SQL_NULL_HSTMT, "SQLTablePrivileges");
  3250. efree(result);
  3251. RETURN_FALSE;
  3252. }
  3253. result->numparams = 0;
  3254. SQLNumResultCols(result->stmt, &(result->numcols));
  3255. if (result->numcols > 0) {
  3256. if (!odbc_bindcols(result TSRMLS_CC)) {
  3257. efree(result);
  3258. RETURN_FALSE;
  3259. }
  3260. } else {
  3261. result->values = NULL;
  3262. }
  3263. result->conn_ptr = conn;
  3264. result->fetched = 0;
  3265. ZEND_REGISTER_RESOURCE(return_value, result, le_result);
  3266. }
  3267. /* }}} */
  3268. #endif /* HAVE_DBMAKER */
  3269. #endif /* HAVE_UODBC */
  3270. /*
  3271. * Local variables:
  3272. * tab-width: 4
  3273. * c-basic-offset: 4
  3274. * End:
  3275. * vim600: sw=4 ts=4 fdm=marker
  3276. * vim<600: sw=4 ts=4
  3277. */