PageRenderTime 64ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 1ms

/ext/pgsql/pgsql.c

http://github.com/php/php-src
C | 7202 lines | 5778 code | 805 blank | 619 comment | 1478 complexity | 38495fc75f0dc23018d5a5adc7c27896 MD5 | raw file
Possible License(s): BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. +----------------------------------------------------------------------+
  3. | Copyright (c) The PHP Group |
  4. +----------------------------------------------------------------------+
  5. | This source file is subject to version 3.01 of the PHP license, |
  6. | that is bundled with this package in the file LICENSE, and is |
  7. | available through the world-wide-web at the following url: |
  8. | http://www.php.net/license/3_01.txt |
  9. | If you did not receive a copy of the PHP license and are unable to |
  10. | obtain it through the world-wide-web, please send a note to |
  11. | license@php.net so we can mail you a copy immediately. |
  12. +----------------------------------------------------------------------+
  13. | Authors: Zeev Suraski <zeev@php.net> |
  14. | Jouni Ahto <jouni.ahto@exdec.fi> |
  15. | Yasuo Ohgaki <yohgaki@php.net> |
  16. | Youichi Iwakiri <yiwakiri@st.rim.or.jp> (pg_copy_*) |
  17. | Chris Kings-Lynne <chriskl@php.net> (v3 protocol) |
  18. +----------------------------------------------------------------------+
  19. */
  20. #include <stdlib.h>
  21. #define PHP_PGSQL_PRIVATE 1
  22. #ifdef HAVE_CONFIG_H
  23. #include "config.h"
  24. #endif
  25. #define SMART_STR_PREALLOC 512
  26. #include "php.h"
  27. #include "php_ini.h"
  28. #include "ext/standard/php_standard.h"
  29. #include "zend_smart_str.h"
  30. #include "ext/pcre/php_pcre.h"
  31. #ifdef PHP_WIN32
  32. # include "win32/time.h"
  33. #endif
  34. #include "php_pgsql.h"
  35. #include "php_globals.h"
  36. #include "zend_exceptions.h"
  37. #if HAVE_PGSQL
  38. #ifndef InvalidOid
  39. #define InvalidOid ((Oid) 0)
  40. #endif
  41. #define PGSQL_ASSOC 1<<0
  42. #define PGSQL_NUM 1<<1
  43. #define PGSQL_BOTH (PGSQL_ASSOC|PGSQL_NUM)
  44. #define PGSQL_NOTICE_LAST 1 /* Get the last notice */
  45. #define PGSQL_NOTICE_ALL 2 /* Get all notices */
  46. #define PGSQL_NOTICE_CLEAR 3 /* Remove notices */
  47. #define PGSQL_STATUS_LONG 1
  48. #define PGSQL_STATUS_STRING 2
  49. #define PGSQL_MAX_LENGTH_OF_LONG 30
  50. #define PGSQL_MAX_LENGTH_OF_DOUBLE 60
  51. #if ZEND_LONG_MAX < UINT_MAX
  52. #define PGSQL_RETURN_OID(oid) do { \
  53. if (oid > ZEND_LONG_MAX) { \
  54. smart_str s = {0}; \
  55. smart_str_append_unsigned(&s, oid); \
  56. smart_str_0(&s); \
  57. RETURN_NEW_STR(s.s); \
  58. } \
  59. RETURN_LONG((zend_long)oid); \
  60. } while(0)
  61. #else
  62. #define PGSQL_RETURN_OID(oid) RETURN_LONG((zend_long)oid)
  63. #endif
  64. #if HAVE_PQSETNONBLOCKING
  65. #define PQ_SETNONBLOCKING(pg_link, flag) PQsetnonblocking(pg_link, flag)
  66. #else
  67. #define PQ_SETNONBLOCKING(pg_link, flag) 0
  68. #endif
  69. #define CHECK_DEFAULT_LINK(x) if ((x) == NULL) { php_error_docref(NULL, E_WARNING, "No PostgreSQL link opened yet"); RETURN_FALSE; }
  70. #define FETCH_DEFAULT_LINK() PGG(default_link)
  71. #ifndef HAVE_PQFREEMEM
  72. #define PQfreemem free
  73. #endif
  74. ZEND_DECLARE_MODULE_GLOBALS(pgsql)
  75. static PHP_GINIT_FUNCTION(pgsql);
  76. /* {{{ arginfo */
  77. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_connect, 0, 0, 1)
  78. ZEND_ARG_INFO(0, connection_string)
  79. ZEND_ARG_INFO(0, connect_type)
  80. ZEND_ARG_INFO(0, host)
  81. ZEND_ARG_INFO(0, port)
  82. ZEND_ARG_INFO(0, options)
  83. ZEND_ARG_INFO(0, tty)
  84. ZEND_ARG_INFO(0, database)
  85. ZEND_END_ARG_INFO()
  86. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_pconnect, 0, 0, 1)
  87. ZEND_ARG_INFO(0, connection_string)
  88. ZEND_ARG_INFO(0, host)
  89. ZEND_ARG_INFO(0, port)
  90. ZEND_ARG_INFO(0, options)
  91. ZEND_ARG_INFO(0, tty)
  92. ZEND_ARG_INFO(0, database)
  93. ZEND_END_ARG_INFO()
  94. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_connect_poll, 0, 0, 0)
  95. ZEND_ARG_INFO(0, connection)
  96. ZEND_END_ARG_INFO()
  97. #if HAVE_PQPARAMETERSTATUS
  98. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_parameter_status, 0, 0, 1)
  99. ZEND_ARG_INFO(0, connection)
  100. ZEND_ARG_INFO(0, param_name)
  101. ZEND_END_ARG_INFO()
  102. #endif
  103. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_close, 0, 0, 0)
  104. ZEND_ARG_INFO(0, connection)
  105. ZEND_END_ARG_INFO()
  106. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_dbname, 0, 0, 0)
  107. ZEND_ARG_INFO(0, connection)
  108. ZEND_END_ARG_INFO()
  109. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_last_error, 0, 0, 0)
  110. ZEND_ARG_INFO(0, connection)
  111. ZEND_END_ARG_INFO()
  112. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_options, 0, 0, 0)
  113. ZEND_ARG_INFO(0, connection)
  114. ZEND_END_ARG_INFO()
  115. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_port, 0, 0, 0)
  116. ZEND_ARG_INFO(0, connection)
  117. ZEND_END_ARG_INFO()
  118. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_tty, 0, 0, 0)
  119. ZEND_ARG_INFO(0, connection)
  120. ZEND_END_ARG_INFO()
  121. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_host, 0, 0, 0)
  122. ZEND_ARG_INFO(0, connection)
  123. ZEND_END_ARG_INFO()
  124. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_version, 0, 0, 0)
  125. ZEND_ARG_INFO(0, connection)
  126. ZEND_END_ARG_INFO()
  127. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_ping, 0, 0, 0)
  128. ZEND_ARG_INFO(0, connection)
  129. ZEND_END_ARG_INFO()
  130. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_query, 0, 0, 0)
  131. ZEND_ARG_INFO(0, connection)
  132. ZEND_ARG_INFO(0, query)
  133. ZEND_END_ARG_INFO()
  134. #if HAVE_PQEXECPARAMS
  135. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_query_params, 0, 0, 0)
  136. ZEND_ARG_INFO(0, connection)
  137. ZEND_ARG_INFO(0, query)
  138. ZEND_ARG_INFO(0, params)
  139. ZEND_END_ARG_INFO()
  140. #endif
  141. #if HAVE_PQPREPARE
  142. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_prepare, 0, 0, 0)
  143. ZEND_ARG_INFO(0, connection)
  144. ZEND_ARG_INFO(0, stmtname)
  145. ZEND_ARG_INFO(0, query)
  146. ZEND_END_ARG_INFO()
  147. #endif
  148. #if HAVE_PQEXECPREPARED
  149. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_execute, 0, 0, 0)
  150. ZEND_ARG_INFO(0, connection)
  151. ZEND_ARG_INFO(0, stmtname)
  152. ZEND_ARG_INFO(0, params)
  153. ZEND_END_ARG_INFO()
  154. #endif
  155. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_num_rows, 0, 0, 1)
  156. ZEND_ARG_INFO(0, result)
  157. ZEND_END_ARG_INFO()
  158. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_num_fields, 0, 0, 1)
  159. ZEND_ARG_INFO(0, result)
  160. ZEND_END_ARG_INFO()
  161. #if HAVE_PQCMDTUPLES
  162. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_affected_rows, 0, 0, 1)
  163. ZEND_ARG_INFO(0, result)
  164. ZEND_END_ARG_INFO()
  165. #endif
  166. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_last_notice, 0, 0, 1)
  167. ZEND_ARG_INFO(0, connection)
  168. ZEND_ARG_INFO(0, option)
  169. ZEND_END_ARG_INFO()
  170. #ifdef HAVE_PQFTABLE
  171. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_table, 0, 0, 2)
  172. ZEND_ARG_INFO(0, result)
  173. ZEND_ARG_INFO(0, field_number)
  174. ZEND_ARG_INFO(0, oid_only)
  175. ZEND_END_ARG_INFO()
  176. #endif
  177. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_name, 0, 0, 2)
  178. ZEND_ARG_INFO(0, result)
  179. ZEND_ARG_INFO(0, field_number)
  180. ZEND_END_ARG_INFO()
  181. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_size, 0, 0, 2)
  182. ZEND_ARG_INFO(0, result)
  183. ZEND_ARG_INFO(0, field_number)
  184. ZEND_END_ARG_INFO()
  185. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_type, 0, 0, 2)
  186. ZEND_ARG_INFO(0, result)
  187. ZEND_ARG_INFO(0, field_number)
  188. ZEND_END_ARG_INFO()
  189. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_type_oid, 0, 0, 2)
  190. ZEND_ARG_INFO(0, result)
  191. ZEND_ARG_INFO(0, field_number)
  192. ZEND_END_ARG_INFO()
  193. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_num, 0, 0, 2)
  194. ZEND_ARG_INFO(0, result)
  195. ZEND_ARG_INFO(0, field_name)
  196. ZEND_END_ARG_INFO()
  197. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_result, 0, 0, 1)
  198. ZEND_ARG_INFO(0, result)
  199. ZEND_ARG_INFO(0, row_number)
  200. ZEND_ARG_INFO(0, field_name)
  201. ZEND_END_ARG_INFO()
  202. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_row, 0, 0, 1)
  203. ZEND_ARG_INFO(0, result)
  204. ZEND_ARG_INFO(0, row)
  205. ZEND_ARG_INFO(0, result_type)
  206. ZEND_END_ARG_INFO()
  207. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_assoc, 0, 0, 1)
  208. ZEND_ARG_INFO(0, result)
  209. ZEND_ARG_INFO(0, row)
  210. ZEND_END_ARG_INFO()
  211. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_array, 0, 0, 1)
  212. ZEND_ARG_INFO(0, result)
  213. ZEND_ARG_INFO(0, row)
  214. ZEND_ARG_INFO(0, result_type)
  215. ZEND_END_ARG_INFO()
  216. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_object, 0, 0, 1)
  217. ZEND_ARG_INFO(0, result)
  218. ZEND_ARG_INFO(0, row)
  219. ZEND_ARG_INFO(0, class_name)
  220. ZEND_ARG_INFO(0, l)
  221. ZEND_ARG_INFO(0, ctor_params)
  222. ZEND_END_ARG_INFO()
  223. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_all, 0, 0, 1)
  224. ZEND_ARG_INFO(0, result)
  225. ZEND_ARG_INFO(0, result_type)
  226. ZEND_END_ARG_INFO()
  227. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_all_columns, 0, 0, 1)
  228. ZEND_ARG_INFO(0, result)
  229. ZEND_ARG_INFO(0, column_number)
  230. ZEND_END_ARG_INFO()
  231. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_result_seek, 0, 0, 2)
  232. ZEND_ARG_INFO(0, result)
  233. ZEND_ARG_INFO(0, offset)
  234. ZEND_END_ARG_INFO()
  235. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_prtlen, 0, 0, 1)
  236. ZEND_ARG_INFO(0, result)
  237. ZEND_ARG_INFO(0, row)
  238. ZEND_ARG_INFO(0, field_name_or_number)
  239. ZEND_END_ARG_INFO()
  240. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_is_null, 0, 0, 1)
  241. ZEND_ARG_INFO(0, result)
  242. ZEND_ARG_INFO(0, row)
  243. ZEND_ARG_INFO(0, field_name_or_number)
  244. ZEND_END_ARG_INFO()
  245. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_free_result, 0, 0, 1)
  246. ZEND_ARG_INFO(0, result)
  247. ZEND_END_ARG_INFO()
  248. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_last_oid, 0, 0, 1)
  249. ZEND_ARG_INFO(0, result)
  250. ZEND_END_ARG_INFO()
  251. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_trace, 0, 0, 1)
  252. ZEND_ARG_INFO(0, filename)
  253. ZEND_ARG_INFO(0, mode)
  254. ZEND_ARG_INFO(0, connection)
  255. ZEND_END_ARG_INFO()
  256. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_untrace, 0, 0, 0)
  257. ZEND_ARG_INFO(0, connection)
  258. ZEND_END_ARG_INFO()
  259. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_create, 0, 0, 0)
  260. ZEND_ARG_INFO(0, connection)
  261. ZEND_ARG_INFO(0, large_object_id)
  262. ZEND_END_ARG_INFO()
  263. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_unlink, 0, 0, 0)
  264. ZEND_ARG_INFO(0, connection)
  265. ZEND_ARG_INFO(0, large_object_oid)
  266. ZEND_END_ARG_INFO()
  267. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_open, 0, 0, 0)
  268. ZEND_ARG_INFO(0, connection)
  269. ZEND_ARG_INFO(0, large_object_oid)
  270. ZEND_ARG_INFO(0, mode)
  271. ZEND_END_ARG_INFO()
  272. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_close, 0, 0, 1)
  273. ZEND_ARG_INFO(0, large_object)
  274. ZEND_END_ARG_INFO()
  275. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_read, 0, 0, 1)
  276. ZEND_ARG_INFO(0, large_object)
  277. ZEND_ARG_INFO(0, len)
  278. ZEND_END_ARG_INFO()
  279. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_write, 0, 0, 2)
  280. ZEND_ARG_INFO(0, large_object)
  281. ZEND_ARG_INFO(0, buf)
  282. ZEND_ARG_INFO(0, len)
  283. ZEND_END_ARG_INFO()
  284. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_read_all, 0, 0, 1)
  285. ZEND_ARG_INFO(0, large_object)
  286. ZEND_END_ARG_INFO()
  287. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_import, 0, 0, 0)
  288. ZEND_ARG_INFO(0, connection)
  289. ZEND_ARG_INFO(0, filename)
  290. ZEND_ARG_INFO(0, large_object_oid)
  291. ZEND_END_ARG_INFO()
  292. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_export, 0, 0, 0)
  293. ZEND_ARG_INFO(0, connection)
  294. ZEND_ARG_INFO(0, objoid)
  295. ZEND_ARG_INFO(0, filename)
  296. ZEND_END_ARG_INFO()
  297. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_seek, 0, 0, 2)
  298. ZEND_ARG_INFO(0, large_object)
  299. ZEND_ARG_INFO(0, offset)
  300. ZEND_ARG_INFO(0, whence)
  301. ZEND_END_ARG_INFO()
  302. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_tell, 0, 0, 1)
  303. ZEND_ARG_INFO(0, large_object)
  304. ZEND_END_ARG_INFO()
  305. #if HAVE_PG_LO_TRUNCATE
  306. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_truncate, 0, 0, 1)
  307. ZEND_ARG_INFO(0, large_object)
  308. ZEND_ARG_INFO(0, size)
  309. ZEND_END_ARG_INFO()
  310. #endif
  311. #if HAVE_PQSETERRORVERBOSITY
  312. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_set_error_verbosity, 0, 0, 0)
  313. ZEND_ARG_INFO(0, connection)
  314. ZEND_ARG_INFO(0, verbosity)
  315. ZEND_END_ARG_INFO()
  316. #endif
  317. #if HAVE_PQCLIENTENCODING
  318. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_set_client_encoding, 0, 0, 0)
  319. ZEND_ARG_INFO(0, connection)
  320. ZEND_ARG_INFO(0, encoding)
  321. ZEND_END_ARG_INFO()
  322. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_client_encoding, 0, 0, 0)
  323. ZEND_ARG_INFO(0, connection)
  324. ZEND_END_ARG_INFO()
  325. #endif
  326. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_end_copy, 0, 0, 0)
  327. ZEND_ARG_INFO(0, connection)
  328. ZEND_END_ARG_INFO()
  329. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_put_line, 0, 0, 0)
  330. ZEND_ARG_INFO(0, connection)
  331. ZEND_ARG_INFO(0, query)
  332. ZEND_END_ARG_INFO()
  333. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_copy_to, 0, 0, 2)
  334. ZEND_ARG_INFO(0, connection)
  335. ZEND_ARG_INFO(0, table_name)
  336. ZEND_ARG_INFO(0, delimiter)
  337. ZEND_ARG_INFO(0, null_as)
  338. ZEND_END_ARG_INFO()
  339. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_copy_from, 0, 0, 3)
  340. ZEND_ARG_INFO(0, connection)
  341. ZEND_ARG_INFO(0, table_name)
  342. ZEND_ARG_INFO(0, rows)
  343. ZEND_ARG_INFO(0, delimiter)
  344. ZEND_ARG_INFO(0, null_as)
  345. ZEND_END_ARG_INFO()
  346. #if HAVE_PQESCAPE
  347. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_escape_string, 0, 0, 0)
  348. ZEND_ARG_INFO(0, connection)
  349. ZEND_ARG_INFO(0, data)
  350. ZEND_END_ARG_INFO()
  351. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_escape_bytea, 0, 0, 0)
  352. ZEND_ARG_INFO(0, connection)
  353. ZEND_ARG_INFO(0, data)
  354. ZEND_END_ARG_INFO()
  355. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_unescape_bytea, 0, 0, 1)
  356. ZEND_ARG_INFO(0, data)
  357. ZEND_END_ARG_INFO()
  358. #endif
  359. #if HAVE_PQESCAPE
  360. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_escape_literal, 0, 0, 0)
  361. ZEND_ARG_INFO(0, connection)
  362. ZEND_ARG_INFO(0, data)
  363. ZEND_END_ARG_INFO()
  364. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_escape_identifier, 0, 0, 0)
  365. ZEND_ARG_INFO(0, connection)
  366. ZEND_ARG_INFO(0, data)
  367. ZEND_END_ARG_INFO()
  368. #endif
  369. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_result_error, 0, 0, 1)
  370. ZEND_ARG_INFO(0, result)
  371. ZEND_END_ARG_INFO()
  372. #if HAVE_PQRESULTERRORFIELD
  373. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_result_error_field, 0, 0, 2)
  374. ZEND_ARG_INFO(0, result)
  375. ZEND_ARG_INFO(0, fieldcode)
  376. ZEND_END_ARG_INFO()
  377. #endif
  378. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_connection_status, 0, 0, 1)
  379. ZEND_ARG_INFO(0, connection)
  380. ZEND_END_ARG_INFO()
  381. #if HAVE_PGTRANSACTIONSTATUS
  382. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_transaction_status, 0, 0, 1)
  383. ZEND_ARG_INFO(0, connection)
  384. ZEND_END_ARG_INFO()
  385. #endif
  386. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_connection_reset, 0, 0, 1)
  387. ZEND_ARG_INFO(0, connection)
  388. ZEND_END_ARG_INFO()
  389. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_cancel_query, 0, 0, 1)
  390. ZEND_ARG_INFO(0, connection)
  391. ZEND_END_ARG_INFO()
  392. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_connection_busy, 0, 0, 1)
  393. ZEND_ARG_INFO(0, connection)
  394. ZEND_END_ARG_INFO()
  395. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_send_query, 0, 0, 2)
  396. ZEND_ARG_INFO(0, connection)
  397. ZEND_ARG_INFO(0, query)
  398. ZEND_END_ARG_INFO()
  399. #if HAVE_PQSENDQUERYPARAMS
  400. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_send_query_params, 0, 0, 3)
  401. ZEND_ARG_INFO(0, connection)
  402. ZEND_ARG_INFO(0, query)
  403. ZEND_ARG_INFO(0, params)
  404. ZEND_END_ARG_INFO()
  405. #endif
  406. #if HAVE_PQSENDPREPARE
  407. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_send_prepare, 0, 0, 3)
  408. ZEND_ARG_INFO(0, connection)
  409. ZEND_ARG_INFO(0, stmtname)
  410. ZEND_ARG_INFO(0, query)
  411. ZEND_END_ARG_INFO()
  412. #endif
  413. #if HAVE_PQSENDQUERYPREPARED
  414. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_send_execute, 0, 0, 3)
  415. ZEND_ARG_INFO(0, connection)
  416. ZEND_ARG_INFO(0, stmtname)
  417. ZEND_ARG_INFO(0, params)
  418. ZEND_END_ARG_INFO()
  419. #endif
  420. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_get_result, 0, 0, 1)
  421. ZEND_ARG_INFO(0, connection)
  422. ZEND_END_ARG_INFO()
  423. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_result_status, 0, 0, 1)
  424. ZEND_ARG_INFO(0, result)
  425. ZEND_ARG_INFO(0, result_type)
  426. ZEND_END_ARG_INFO()
  427. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_get_notify, 0, 0, 0)
  428. ZEND_ARG_INFO(0, connection)
  429. ZEND_ARG_INFO(0, e)
  430. ZEND_END_ARG_INFO()
  431. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_get_pid, 0, 0, 0)
  432. ZEND_ARG_INFO(0, connection)
  433. ZEND_END_ARG_INFO()
  434. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_socket, 0, 0, 1)
  435. ZEND_ARG_INFO(0, connection)
  436. ZEND_END_ARG_INFO()
  437. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_consume_input, 0, 0, 1)
  438. ZEND_ARG_INFO(0, connection)
  439. ZEND_END_ARG_INFO()
  440. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_flush, 0, 0, 1)
  441. ZEND_ARG_INFO(0, connection)
  442. ZEND_END_ARG_INFO()
  443. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_meta_data, 0, 0, 2)
  444. ZEND_ARG_INFO(0, db)
  445. ZEND_ARG_INFO(0, table)
  446. ZEND_END_ARG_INFO()
  447. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_convert, 0, 0, 3)
  448. ZEND_ARG_INFO(0, db)
  449. ZEND_ARG_INFO(0, table)
  450. ZEND_ARG_INFO(0, values)
  451. ZEND_ARG_INFO(0, options)
  452. ZEND_END_ARG_INFO()
  453. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_insert, 0, 0, 3)
  454. ZEND_ARG_INFO(0, db)
  455. ZEND_ARG_INFO(0, table)
  456. ZEND_ARG_INFO(0, values)
  457. ZEND_ARG_INFO(0, options)
  458. ZEND_END_ARG_INFO()
  459. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_update, 0, 0, 4)
  460. ZEND_ARG_INFO(0, db)
  461. ZEND_ARG_INFO(0, table)
  462. ZEND_ARG_INFO(0, fields)
  463. ZEND_ARG_INFO(0, ids)
  464. ZEND_ARG_INFO(0, options)
  465. ZEND_END_ARG_INFO()
  466. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_delete, 0, 0, 3)
  467. ZEND_ARG_INFO(0, db)
  468. ZEND_ARG_INFO(0, table)
  469. ZEND_ARG_INFO(0, ids)
  470. ZEND_ARG_INFO(0, options)
  471. ZEND_END_ARG_INFO()
  472. ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_select, 0, 0, 3)
  473. ZEND_ARG_INFO(0, db)
  474. ZEND_ARG_INFO(0, table)
  475. ZEND_ARG_INFO(0, ids)
  476. ZEND_ARG_INFO(0, options)
  477. ZEND_ARG_INFO(0, result_type)
  478. ZEND_END_ARG_INFO()
  479. /* }}} */
  480. /* {{{ pgsql_functions[]
  481. */
  482. static const zend_function_entry pgsql_functions[] = {
  483. /* connection functions */
  484. PHP_FE(pg_connect, arginfo_pg_connect)
  485. PHP_FE(pg_pconnect, arginfo_pg_pconnect)
  486. PHP_FE(pg_connect_poll, arginfo_pg_connect_poll)
  487. PHP_FE(pg_close, arginfo_pg_close)
  488. PHP_FE(pg_connection_status, arginfo_pg_connection_status)
  489. PHP_FE(pg_connection_busy, arginfo_pg_connection_busy)
  490. PHP_FE(pg_connection_reset, arginfo_pg_connection_reset)
  491. PHP_FE(pg_host, arginfo_pg_host)
  492. PHP_FE(pg_dbname, arginfo_pg_dbname)
  493. PHP_FE(pg_port, arginfo_pg_port)
  494. PHP_FE(pg_tty, arginfo_pg_tty)
  495. PHP_FE(pg_options, arginfo_pg_options)
  496. PHP_FE(pg_version, arginfo_pg_version)
  497. PHP_FE(pg_ping, arginfo_pg_ping)
  498. #if HAVE_PQPARAMETERSTATUS
  499. PHP_FE(pg_parameter_status, arginfo_pg_parameter_status)
  500. #endif
  501. #if HAVE_PGTRANSACTIONSTATUS
  502. PHP_FE(pg_transaction_status, arginfo_pg_transaction_status)
  503. #endif
  504. /* query functions */
  505. PHP_FE(pg_query, arginfo_pg_query)
  506. #if HAVE_PQEXECPARAMS
  507. PHP_FE(pg_query_params, arginfo_pg_query_params)
  508. #endif
  509. #if HAVE_PQPREPARE
  510. PHP_FE(pg_prepare, arginfo_pg_prepare)
  511. #endif
  512. #if HAVE_PQEXECPREPARED
  513. PHP_FE(pg_execute, arginfo_pg_execute)
  514. #endif
  515. PHP_FE(pg_send_query, arginfo_pg_send_query)
  516. #if HAVE_PQSENDQUERYPARAMS
  517. PHP_FE(pg_send_query_params, arginfo_pg_send_query_params)
  518. #endif
  519. #if HAVE_PQSENDPREPARE
  520. PHP_FE(pg_send_prepare, arginfo_pg_send_prepare)
  521. #endif
  522. #if HAVE_PQSENDQUERYPREPARED
  523. PHP_FE(pg_send_execute, arginfo_pg_send_execute)
  524. #endif
  525. PHP_FE(pg_cancel_query, arginfo_pg_cancel_query)
  526. /* result functions */
  527. PHP_FE(pg_fetch_result, arginfo_pg_fetch_result)
  528. PHP_FE(pg_fetch_row, arginfo_pg_fetch_row)
  529. PHP_FE(pg_fetch_assoc, arginfo_pg_fetch_assoc)
  530. PHP_FE(pg_fetch_array, arginfo_pg_fetch_array)
  531. PHP_FE(pg_fetch_object, arginfo_pg_fetch_object)
  532. PHP_FE(pg_fetch_all, arginfo_pg_fetch_all)
  533. PHP_FE(pg_fetch_all_columns, arginfo_pg_fetch_all_columns)
  534. #if HAVE_PQCMDTUPLES
  535. PHP_FE(pg_affected_rows,arginfo_pg_affected_rows)
  536. #endif
  537. PHP_FE(pg_get_result, arginfo_pg_get_result)
  538. PHP_FE(pg_result_seek, arginfo_pg_result_seek)
  539. PHP_FE(pg_result_status,arginfo_pg_result_status)
  540. PHP_FE(pg_free_result, arginfo_pg_free_result)
  541. PHP_FE(pg_last_oid, arginfo_pg_last_oid)
  542. PHP_FE(pg_num_rows, arginfo_pg_num_rows)
  543. PHP_FE(pg_num_fields, arginfo_pg_num_fields)
  544. PHP_FE(pg_field_name, arginfo_pg_field_name)
  545. PHP_FE(pg_field_num, arginfo_pg_field_num)
  546. PHP_FE(pg_field_size, arginfo_pg_field_size)
  547. PHP_FE(pg_field_type, arginfo_pg_field_type)
  548. PHP_FE(pg_field_type_oid, arginfo_pg_field_type_oid)
  549. PHP_FE(pg_field_prtlen, arginfo_pg_field_prtlen)
  550. PHP_FE(pg_field_is_null,arginfo_pg_field_is_null)
  551. #ifdef HAVE_PQFTABLE
  552. PHP_FE(pg_field_table, arginfo_pg_field_table)
  553. #endif
  554. /* async message function */
  555. PHP_FE(pg_get_notify, arginfo_pg_get_notify)
  556. PHP_FE(pg_socket, arginfo_pg_socket)
  557. PHP_FE(pg_consume_input,arginfo_pg_consume_input)
  558. PHP_FE(pg_flush, arginfo_pg_flush)
  559. PHP_FE(pg_get_pid, arginfo_pg_get_pid)
  560. /* error message functions */
  561. PHP_FE(pg_result_error, arginfo_pg_result_error)
  562. #if HAVE_PQRESULTERRORFIELD
  563. PHP_FE(pg_result_error_field, arginfo_pg_result_error_field)
  564. #endif
  565. PHP_FE(pg_last_error, arginfo_pg_last_error)
  566. PHP_FE(pg_last_notice, arginfo_pg_last_notice)
  567. /* copy functions */
  568. PHP_FE(pg_put_line, arginfo_pg_put_line)
  569. PHP_FE(pg_end_copy, arginfo_pg_end_copy)
  570. PHP_FE(pg_copy_to, arginfo_pg_copy_to)
  571. PHP_FE(pg_copy_from, arginfo_pg_copy_from)
  572. /* debug functions */
  573. PHP_FE(pg_trace, arginfo_pg_trace)
  574. PHP_FE(pg_untrace, arginfo_pg_untrace)
  575. /* large object functions */
  576. PHP_FE(pg_lo_create, arginfo_pg_lo_create)
  577. PHP_FE(pg_lo_unlink, arginfo_pg_lo_unlink)
  578. PHP_FE(pg_lo_open, arginfo_pg_lo_open)
  579. PHP_FE(pg_lo_close, arginfo_pg_lo_close)
  580. PHP_FE(pg_lo_read, arginfo_pg_lo_read)
  581. PHP_FE(pg_lo_write, arginfo_pg_lo_write)
  582. PHP_FE(pg_lo_read_all, arginfo_pg_lo_read_all)
  583. PHP_FE(pg_lo_import, arginfo_pg_lo_import)
  584. PHP_FE(pg_lo_export, arginfo_pg_lo_export)
  585. PHP_FE(pg_lo_seek, arginfo_pg_lo_seek)
  586. PHP_FE(pg_lo_tell, arginfo_pg_lo_tell)
  587. #if HAVE_PG_LO_TRUNCATE
  588. PHP_FE(pg_lo_truncate, arginfo_pg_lo_truncate)
  589. #endif
  590. /* utility functions */
  591. #if HAVE_PQESCAPE
  592. PHP_FE(pg_escape_string, arginfo_pg_escape_string)
  593. PHP_FE(pg_escape_bytea, arginfo_pg_escape_bytea)
  594. PHP_FE(pg_unescape_bytea, arginfo_pg_unescape_bytea)
  595. PHP_FE(pg_escape_literal, arginfo_pg_escape_literal)
  596. PHP_FE(pg_escape_identifier, arginfo_pg_escape_identifier)
  597. #endif
  598. #if HAVE_PQSETERRORVERBOSITY
  599. PHP_FE(pg_set_error_verbosity, arginfo_pg_set_error_verbosity)
  600. #endif
  601. #if HAVE_PQCLIENTENCODING
  602. PHP_FE(pg_client_encoding, arginfo_pg_client_encoding)
  603. PHP_FE(pg_set_client_encoding, arginfo_pg_set_client_encoding)
  604. #endif
  605. /* misc function */
  606. PHP_FE(pg_meta_data, arginfo_pg_meta_data)
  607. PHP_FE(pg_convert, arginfo_pg_convert)
  608. PHP_FE(pg_insert, arginfo_pg_insert)
  609. PHP_FE(pg_update, arginfo_pg_update)
  610. PHP_FE(pg_delete, arginfo_pg_delete)
  611. PHP_FE(pg_select, arginfo_pg_select)
  612. /* aliases for downwards compatibility */
  613. PHP_FALIAS(pg_exec, pg_query, arginfo_pg_query)
  614. PHP_FALIAS(pg_getlastoid, pg_last_oid, arginfo_pg_last_oid)
  615. #if HAVE_PQCMDTUPLES
  616. PHP_FALIAS(pg_cmdtuples, pg_affected_rows, arginfo_pg_affected_rows)
  617. #endif
  618. PHP_FALIAS(pg_errormessage, pg_last_error, arginfo_pg_last_error)
  619. PHP_FALIAS(pg_numrows, pg_num_rows, arginfo_pg_num_rows)
  620. PHP_FALIAS(pg_numfields, pg_num_fields, arginfo_pg_num_fields)
  621. PHP_FALIAS(pg_fieldname, pg_field_name, arginfo_pg_field_name)
  622. PHP_FALIAS(pg_fieldsize, pg_field_size, arginfo_pg_field_size)
  623. PHP_FALIAS(pg_fieldtype, pg_field_type, arginfo_pg_field_type)
  624. PHP_FALIAS(pg_fieldnum, pg_field_num, arginfo_pg_field_num)
  625. PHP_FALIAS(pg_fieldprtlen, pg_field_prtlen, arginfo_pg_field_prtlen)
  626. PHP_FALIAS(pg_fieldisnull, pg_field_is_null, arginfo_pg_field_is_null)
  627. PHP_FALIAS(pg_freeresult, pg_free_result, arginfo_pg_free_result)
  628. PHP_FALIAS(pg_result, pg_fetch_result, arginfo_pg_get_result)
  629. PHP_FALIAS(pg_loreadall, pg_lo_read_all, arginfo_pg_lo_read_all)
  630. PHP_FALIAS(pg_locreate, pg_lo_create, arginfo_pg_lo_create)
  631. PHP_FALIAS(pg_lounlink, pg_lo_unlink, arginfo_pg_lo_unlink)
  632. PHP_FALIAS(pg_loopen, pg_lo_open, arginfo_pg_lo_open)
  633. PHP_FALIAS(pg_loclose, pg_lo_close, arginfo_pg_lo_close)
  634. PHP_FALIAS(pg_loread, pg_lo_read, arginfo_pg_lo_read)
  635. PHP_FALIAS(pg_lowrite, pg_lo_write, arginfo_pg_lo_write)
  636. PHP_FALIAS(pg_loimport, pg_lo_import, arginfo_pg_lo_import)
  637. PHP_FALIAS(pg_loexport, pg_lo_export, arginfo_pg_lo_export)
  638. #if HAVE_PQCLIENTENCODING
  639. PHP_FALIAS(pg_clientencoding, pg_client_encoding, arginfo_pg_client_encoding)
  640. PHP_FALIAS(pg_setclientencoding, pg_set_client_encoding, arginfo_pg_set_client_encoding)
  641. #endif
  642. PHP_FE_END
  643. };
  644. /* }}} */
  645. /* {{{ pgsql_module_entry
  646. */
  647. zend_module_entry pgsql_module_entry = {
  648. STANDARD_MODULE_HEADER,
  649. "pgsql",
  650. pgsql_functions,
  651. PHP_MINIT(pgsql),
  652. PHP_MSHUTDOWN(pgsql),
  653. PHP_RINIT(pgsql),
  654. PHP_RSHUTDOWN(pgsql),
  655. PHP_MINFO(pgsql),
  656. PHP_PGSQL_VERSION,
  657. PHP_MODULE_GLOBALS(pgsql),
  658. PHP_GINIT(pgsql),
  659. NULL,
  660. NULL,
  661. STANDARD_MODULE_PROPERTIES_EX
  662. };
  663. /* }}} */
  664. #ifdef COMPILE_DL_PGSQL
  665. #ifdef ZTS
  666. ZEND_TSRMLS_CACHE_DEFINE()
  667. #endif
  668. ZEND_GET_MODULE(pgsql)
  669. #endif
  670. static int le_link, le_plink, le_result, le_lofp, le_string;
  671. /* Compatibility definitions */
  672. #ifndef HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT
  673. #define pg_encoding_to_char(x) "SQL_ASCII"
  674. #endif
  675. #if !HAVE_PQESCAPE_CONN
  676. #define PQescapeStringConn(conn, to, from, len, error) PQescapeString(to, from, len)
  677. #endif
  678. #if HAVE_PQESCAPELITERAL
  679. #define PGSQLescapeLiteral(conn, str, len) PQescapeLiteral(conn, str, len)
  680. #define PGSQLescapeIdentifier(conn, str, len) PQescapeIdentifier(conn, str, len)
  681. #define PGSQLfree(a) PQfreemem(a)
  682. #else
  683. #define PGSQLescapeLiteral(conn, str, len) php_pgsql_PQescapeInternal(conn, str, len, 1, 0)
  684. #define PGSQLescapeLiteral2(conn, str, len) php_pgsql_PQescapeInternal(conn, str, len, 1, 1)
  685. #define PGSQLescapeIdentifier(conn, str, len) php_pgsql_PQescapeInternal(conn, str, len, 0, 0)
  686. #define PGSQLfree(a) efree(a)
  687. /* emulate libpq's PQescapeInternal() 9.0 or later */
  688. static char *php_pgsql_PQescapeInternal(PGconn *conn, const char *str, size_t len, int escape_literal, int safe) /* {{{ */
  689. {
  690. char *result, *rp, *s;
  691. if (!conn) {
  692. return NULL;
  693. }
  694. /* allocate enough memory */
  695. rp = result = (char *)safe_emalloc(len, 2, 5); /* leading " E" needs extra 2 bytes + quote_chars on both end for 2 bytes + NULL */
  696. if (escape_literal) {
  697. if (safe) {
  698. size_t new_len;
  699. char *tmp = (char *)safe_emalloc(len, 2, 1);
  700. *rp++ = '\'';
  701. /* PQescapeString does not escape \, but it handles multibyte chars safely.
  702. This escape is incompatible with PQescapeLiteral. */
  703. new_len = PQescapeStringConn(conn, tmp, str, len, NULL);
  704. strncpy(rp, tmp, new_len);
  705. efree(tmp);
  706. rp += new_len;
  707. } else {
  708. char *encoding;
  709. size_t tmp_len;
  710. /* This is compatible with PQescapeLiteral, but it cannot handle multbyte chars
  711. such as SJIS, BIG5. Raise warning and return NULL by checking
  712. client_encoding. */
  713. encoding = (char *) pg_encoding_to_char(PQclientEncoding(conn));
  714. if (!strncmp(encoding, "SJIS", sizeof("SJIS")-1) ||
  715. !strncmp(encoding, "SHIFT_JIS_2004", sizeof("SHIFT_JIS_2004")-1) ||
  716. !strncmp(encoding, "BIG5", sizeof("BIG5")-1) ||
  717. !strncmp(encoding, "GB18030", sizeof("GB18030")-1) ||
  718. !strncmp(encoding, "GBK", sizeof("GBK")-1) ||
  719. !strncmp(encoding, "JOHAB", sizeof("JOHAB")-1) ||
  720. !strncmp(encoding, "UHC", sizeof("UHC")-1) ) {
  721. php_error_docref(NULL, E_WARNING, "Unsafe encoding is used. Do not use '%s' encoding or use PostgreSQL 9.0 or later libpq.", encoding);
  722. }
  723. /* check backslashes */
  724. tmp_len = strspn(str, "\\");
  725. if (tmp_len != len) {
  726. /* add " E" for escaping slashes */
  727. *rp++ = ' ';
  728. *rp++ = 'E';
  729. }
  730. *rp++ = '\'';
  731. for (s = (char *)str; s - str < len; ++s) {
  732. if (*s == '\'' || *s == '\\') {
  733. *rp++ = *s;
  734. *rp++ = *s;
  735. } else {
  736. *rp++ = *s;
  737. }
  738. }
  739. }
  740. *rp++ = '\'';
  741. } else {
  742. /* Identifier escape. */
  743. *rp++ = '"';
  744. for (s = (char *)str; s - str < len; ++s) {
  745. if (*s == '"') {
  746. *rp++ = '"';
  747. *rp++ = '"';
  748. } else {
  749. *rp++ = *s;
  750. }
  751. }
  752. *rp++ = '"';
  753. }
  754. *rp = '\0';
  755. return result;
  756. }
  757. /* }}} */
  758. #endif
  759. /* {{{ _php_pgsql_trim_message */
  760. static char * _php_pgsql_trim_message(const char *message, size_t *len)
  761. {
  762. register size_t i = strlen(message);
  763. if (i>2 && (message[i-2] == '\r' || message[i-2] == '\n') && message[i-1] == '.') {
  764. --i;
  765. }
  766. while (i>1 && (message[i-1] == '\r' || message[i-1] == '\n')) {
  767. --i;
  768. }
  769. if (len) {
  770. *len = i;
  771. }
  772. return estrndup(message, i);
  773. }
  774. /* }}} */
  775. /* {{{ _php_pgsql_trim_result */
  776. static inline char * _php_pgsql_trim_result(PGconn * pgsql, char **buf)
  777. {
  778. return *buf = _php_pgsql_trim_message(PQerrorMessage(pgsql), NULL);
  779. }
  780. /* }}} */
  781. #define PQErrorMessageTrim(pgsql, buf) _php_pgsql_trim_result(pgsql, buf)
  782. #define PHP_PQ_ERROR(text, pgsql) { \
  783. char *msgbuf = _php_pgsql_trim_message(PQerrorMessage(pgsql), NULL); \
  784. php_error_docref(NULL, E_WARNING, text, msgbuf); \
  785. efree(msgbuf); \
  786. } \
  787. /* {{{ php_pgsql_set_default_link
  788. */
  789. static void php_pgsql_set_default_link(zend_resource *res)
  790. {
  791. GC_ADDREF(res);
  792. if (PGG(default_link) != NULL) {
  793. zend_list_delete(PGG(default_link));
  794. }
  795. PGG(default_link) = res;
  796. }
  797. /* }}} */
  798. /* {{{ _close_pgsql_link
  799. */
  800. static void _close_pgsql_link(zend_resource *rsrc)
  801. {
  802. PGconn *link = (PGconn *)rsrc->ptr;
  803. PGresult *res;
  804. zval *hash;
  805. while ((res = PQgetResult(link))) {
  806. PQclear(res);
  807. }
  808. PQfinish(link);
  809. PGG(num_links)--;
  810. /* Remove connection hash for this link */
  811. hash = zend_hash_index_find(&PGG(hashes), (uintptr_t) link);
  812. if (hash) {
  813. zend_hash_index_del(&PGG(hashes), (uintptr_t) link);
  814. zend_hash_del(&EG(regular_list), Z_STR_P(hash));
  815. }
  816. }
  817. /* }}} */
  818. /* {{{ _close_pgsql_plink
  819. */
  820. static void _close_pgsql_plink(zend_resource *rsrc)
  821. {
  822. PGconn *link = (PGconn *)rsrc->ptr;
  823. PGresult *res;
  824. while ((res = PQgetResult(link))) {
  825. PQclear(res);
  826. }
  827. PQfinish(link);
  828. PGG(num_persistent)--;
  829. PGG(num_links)--;
  830. }
  831. /* }}} */
  832. /* {{{ _php_pgsql_notice_handler
  833. */
  834. static void _php_pgsql_notice_handler(void *resource_id, const char *message)
  835. {
  836. zval *notices;
  837. zval tmp;
  838. char *trimed_message;
  839. size_t trimed_message_len;
  840. if (! PGG(ignore_notices)) {
  841. notices = zend_hash_index_find(&PGG(notices), (zend_ulong)resource_id);
  842. if (!notices) {
  843. array_init(&tmp);
  844. notices = &tmp;
  845. zend_hash_index_update(&PGG(notices), (zend_ulong)resource_id, notices);
  846. }
  847. trimed_message = _php_pgsql_trim_message(message, &trimed_message_len);
  848. if (PGG(log_notices)) {
  849. php_error_docref(NULL, E_NOTICE, "%s", trimed_message);
  850. }
  851. add_next_index_stringl(notices, trimed_message, trimed_message_len);
  852. efree(trimed_message);
  853. }
  854. }
  855. /* }}} */
  856. /* {{{ _rollback_transactions
  857. */
  858. static int _rollback_transactions(zval *el)
  859. {
  860. PGconn *link;
  861. PGresult *res;
  862. zend_resource *rsrc = Z_RES_P(el);
  863. if (rsrc->type != le_plink)
  864. return 0;
  865. link = (PGconn *) rsrc->ptr;
  866. if (PQ_SETNONBLOCKING(link, 0)) {
  867. php_error_docref("ref.pgsql", E_NOTICE, "Cannot set connection to blocking mode");
  868. return -1;
  869. }
  870. while ((res = PQgetResult(link))) {
  871. PQclear(res);
  872. }
  873. #if HAVE_PGTRANSACTIONSTATUS && HAVE_PQPROTOCOLVERSION
  874. if ((PQprotocolVersion(link) >= 3 && PQtransactionStatus(link) != PQTRANS_IDLE) || PQprotocolVersion(link) < 3)
  875. #endif
  876. {
  877. int orig = PGG(ignore_notices);
  878. PGG(ignore_notices) = 1;
  879. #if HAVE_PGTRANSACTIONSTATUS && HAVE_PQPROTOCOLVERSION
  880. res = PQexec(link,"ROLLBACK;");
  881. #else
  882. res = PQexec(link,"BEGIN;");
  883. PQclear(res);
  884. res = PQexec(link,"ROLLBACK;");
  885. #endif
  886. PQclear(res);
  887. PGG(ignore_notices) = orig;
  888. }
  889. return 0;
  890. }
  891. /* }}} */
  892. /* {{{ _free_ptr
  893. */
  894. static void _free_ptr(zend_resource *rsrc)
  895. {
  896. pgLofp *lofp = (pgLofp *)rsrc->ptr;
  897. efree(lofp);
  898. }
  899. /* }}} */
  900. /* {{{ _free_result
  901. */
  902. static void _free_result(zend_resource *rsrc)
  903. {
  904. pgsql_result_handle *pg_result = (pgsql_result_handle *)rsrc->ptr;
  905. PQclear(pg_result->result);
  906. efree(pg_result);
  907. }
  908. /* }}} */
  909. static int _php_pgsql_detect_identifier_escape(const char *identifier, size_t len) /* {{{ */
  910. {
  911. /* Handle edge case. Cannot be a escaped string */
  912. if (len <= 2) {
  913. return FAILURE;
  914. }
  915. /* Detect double quotes */
  916. if (identifier[0] == '"' && identifier[len-1] == '"') {
  917. size_t i;
  918. /* Detect wrong format of " inside of escaped string */
  919. for (i = 1; i < len-1; i++) {
  920. if (identifier[i] == '"' && (identifier[++i] != '"' || i == len-1)) {
  921. return FAILURE;
  922. }
  923. }
  924. } else {
  925. return FAILURE;
  926. }
  927. /* Escaped properly */
  928. return SUCCESS;
  929. }
  930. /* }}} */
  931. /* {{{ PHP_INI
  932. */
  933. PHP_INI_BEGIN()
  934. STD_PHP_INI_BOOLEAN( "pgsql.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_persistent, zend_pgsql_globals, pgsql_globals)
  935. STD_PHP_INI_ENTRY_EX("pgsql.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_persistent, zend_pgsql_globals, pgsql_globals, display_link_numbers)
  936. STD_PHP_INI_ENTRY_EX("pgsql.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_pgsql_globals, pgsql_globals, display_link_numbers)
  937. STD_PHP_INI_BOOLEAN( "pgsql.auto_reset_persistent", "0", PHP_INI_SYSTEM, OnUpdateBool, auto_reset_persistent, zend_pgsql_globals, pgsql_globals)
  938. STD_PHP_INI_BOOLEAN( "pgsql.ignore_notice", "0", PHP_INI_ALL, OnUpdateBool, ignore_notices, zend_pgsql_globals, pgsql_globals)
  939. STD_PHP_INI_BOOLEAN( "pgsql.log_notice", "0", PHP_INI_ALL, OnUpdateBool, log_notices, zend_pgsql_globals, pgsql_globals)
  940. PHP_INI_END()
  941. /* }}} */
  942. /* {{{ PHP_GINIT_FUNCTION
  943. */
  944. static PHP_GINIT_FUNCTION(pgsql)
  945. {
  946. #if defined(COMPILE_DL_PGSQL) && defined(ZTS)
  947. ZEND_TSRMLS_CACHE_UPDATE();
  948. #endif
  949. memset(pgsql_globals, 0, sizeof(zend_pgsql_globals));
  950. /* Initialize notice message hash at MINIT only */
  951. zend_hash_init_ex(&pgsql_globals->notices, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
  952. zend_hash_init_ex(&pgsql_globals->hashes, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
  953. }
  954. /* }}} */
  955. /* {{{ PHP_MINIT_FUNCTION
  956. */
  957. PHP_MINIT_FUNCTION(pgsql)
  958. {
  959. REGISTER_INI_ENTRIES();
  960. le_link = zend_register_list_destructors_ex(_close_pgsql_link, NULL, "pgsql link", module_number);
  961. le_plink = zend_register_list_destructors_ex(NULL, _close_pgsql_plink, "pgsql link persistent", module_number);
  962. le_result = zend_register_list_destructors_ex(_free_result, NULL, "pgsql result", module_number);
  963. le_lofp = zend_register_list_destructors_ex(_free_ptr, NULL, "pgsql large object", module_number);
  964. le_string = zend_register_list_destructors_ex(_free_ptr, NULL, "pgsql string", module_number);
  965. #if HAVE_PG_CONFIG_H
  966. /* PG_VERSION - libpq version */
  967. REGISTER_STRING_CONSTANT("PGSQL_LIBPQ_VERSION", PG_VERSION, CONST_CS | CONST_PERSISTENT);
  968. REGISTER_STRING_CONSTANT("PGSQL_LIBPQ_VERSION_STR", PG_VERSION_STR, CONST_CS | CONST_PERSISTENT);
  969. #endif
  970. /* For connection option */
  971. REGISTER_LONG_CONSTANT("PGSQL_CONNECT_FORCE_NEW", PGSQL_CONNECT_FORCE_NEW, CONST_CS | CONST_PERSISTENT);
  972. REGISTER_LONG_CONSTANT("PGSQL_CONNECT_ASYNC", PGSQL_CONNECT_ASYNC, CONST_CS | CONST_PERSISTENT);
  973. /* For pg_fetch_array() */
  974. REGISTER_LONG_CONSTANT("PGSQL_ASSOC", PGSQL_ASSOC, CONST_CS | CONST_PERSISTENT);
  975. REGISTER_LONG_CONSTANT("PGSQL_NUM", PGSQL_NUM, CONST_CS | CONST_PERSISTENT);
  976. REGISTER_LONG_CONSTANT("PGSQL_BOTH", PGSQL_BOTH, CONST_CS | CONST_PERSISTENT);
  977. /* For pg_last_notice() */
  978. REGISTER_LONG_CONSTANT("PGSQL_NOTICE_LAST", PGSQL_NOTICE_LAST, CONST_CS | CONST_PERSISTENT);
  979. REGISTER_LONG_CONSTANT("PGSQL_NOTICE_ALL", PGSQL_NOTICE_ALL, CONST_CS | CONST_PERSISTENT);
  980. REGISTER_LONG_CONSTANT("PGSQL_NOTICE_CLEAR", PGSQL_NOTICE_CLEAR, CONST_CS | CONST_PERSISTENT);
  981. /* For pg_connection_status() */
  982. REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_BAD", CONNECTION_BAD, CONST_CS | CONST_PERSISTENT);
  983. REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_OK", CONNECTION_OK, CONST_CS | CONST_PERSISTENT);
  984. REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_STARTED", CONNECTION_STARTED, CONST_CS | CONST_PERSISTENT);
  985. REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_MADE", CONNECTION_MADE, CONST_CS | CONST_PERSISTENT);
  986. REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_AWAITING_RESPONSE", CONNECTION_AWAITING_RESPONSE, CONST_CS | CONST_PERSISTENT);
  987. REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_AUTH_OK", CONNECTION_AUTH_OK, CONST_CS | CONST_PERSISTENT);
  988. #ifdef CONNECTION_SSL_STARTUP
  989. REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_SSL_STARTUP", CONNECTION_SSL_STARTUP, CONST_CS | CONST_PERSISTENT);
  990. #endif
  991. REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_SETENV", CONNECTION_SETENV, CONST_CS | CONST_PERSISTENT);
  992. /* For pg_connect_poll() */
  993. REGISTER_LONG_CONSTANT("PGSQL_POLLING_FAILED", PGRES_POLLING_FAILED, CONST_CS | CONST_PERSISTENT);
  994. REGISTER_LONG_CONSTANT("PGSQL_POLLING_READING", PGRES_POLLING_READING, CONST_CS | CONST_PERSISTENT);
  995. REGISTER_LONG_CONSTANT("PGSQL_POLLING_WRITING", PGRES_POLLING_WRITING, CONST_CS | CONST_PERSISTENT);
  996. REGISTER_LONG_CONSTANT("PGSQL_POLLING_OK", PGRES_POLLING_OK, CONST_CS | CONST_PERSISTENT);
  997. REGISTER_LONG_CONSTANT("PGSQL_POLLING_ACTIVE", PGRES_POLLING_ACTIVE, CONST_CS | CONST_PERSISTENT);
  998. #if HAVE_PGTRANSACTIONSTATUS
  999. /* For pg_transaction_status() */
  1000. REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_IDLE", PQTRANS_IDLE, CONST_CS | CONST_PERSISTENT);
  1001. REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_ACTIVE", PQTRANS_ACTIVE, CONST_CS | CONST_PERSISTENT);
  1002. REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_INTRANS", PQTRANS_INTRANS, CONST_CS | CONST_PERSISTENT);
  1003. REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_INERROR", PQTRANS_INERROR, CONST_CS | CONST_PERSISTENT);
  1004. REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_UNKNOWN", PQTRANS_UNKNOWN, CONST_CS | CONST_PERSISTENT);
  1005. #endif
  1006. #if HAVE_PQSETERRORVERBOSITY
  1007. /* For pg_set_error_verbosity() */
  1008. REGISTER_LONG_CONSTANT("PGSQL_ERRORS_TERSE", PQERRORS_TERSE, CONST_CS | CONST_PERSISTENT);
  1009. REGISTER_LONG_CONSTANT("PGSQL_ERRORS_DEFAULT", PQERRORS_DEFAULT, CONST_CS | CONST_PERSISTENT);
  1010. REGISTER_LONG_CONSTANT("PGSQL_ERRORS_VERBOSE", PQERRORS_VERBOSE, CONST_CS | CONST_PERSISTENT);
  1011. #endif
  1012. /* For lo_seek() */
  1013. REGISTER_LONG_CONSTANT("PGSQL_SEEK_SET", SEEK_SET, CONST_CS | CONST_PERSISTENT);
  1014. REGISTER_LONG_CONSTANT("PGSQL_SEEK_CUR", SEEK_CUR, CONST_CS | CONST_PERSISTENT);
  1015. REGISTER_LONG_CONSTANT("PGSQL_SEEK_END", SEEK_END, CONST_CS | CONST_PERSISTENT);
  1016. /* For pg_result_status() return value type */
  1017. REGISTER_LONG_CONSTANT("PGSQL_STATUS_LONG", PGSQL_STATUS_LONG, CONST_CS | CONST_PERSISTENT);
  1018. REGISTER_LONG_CONSTANT("PGSQL_STATUS_STRING", PGSQL_STATUS_STRING, CONST_CS | CONST_PERSISTENT);
  1019. /* For pg_result_status() return value */
  1020. REGISTER_LONG_CONSTANT("PGSQL_EMPTY_QUERY", PGRES_EMPTY_QUERY, CONST_CS | CONST_PERSISTENT);
  1021. REGISTER_LONG_CONSTANT("PGSQL_COMMAND_OK", PGRES_COMMAND_OK, CONST_CS | CONST_PERSISTENT);
  1022. REGISTER_LONG_CONSTANT("PGSQL_TUPLES_OK", PGRES_TUPLES_OK, CONST_CS | CONST_PERSISTENT);
  1023. REGISTER_LONG_CONSTANT("PGSQL_COPY_OUT", PGRES_COPY_OUT, CONST_CS | CONST_PERSISTENT);
  1024. REGISTER_LONG_CONSTANT("PGSQL_COPY_IN", PGRES_COPY_IN, CONST_CS | CONST_PERSISTENT);
  1025. REGISTER_LONG_CONSTANT("PGSQL_BAD_RESPONSE", PGRES_BAD_RESPONSE, CONST_CS | CONST_PERSISTENT);
  1026. REGISTER_LONG_CONSTANT("PGSQL_NONFATAL_ERROR", PGRES_NONFATAL_ERROR, CONST_CS | CONST_PERSISTENT);
  1027. REGISTER_LONG_CONSTANT("PGSQL_FATAL_ERROR", PGRES_FATAL_ERROR, CONST_CS | CONST_PERSISTENT);
  1028. #if HAVE_PQRESULTERRORFIELD
  1029. /* For pg_result_error_field() field codes */
  1030. REGISTER_LONG_CONSTANT("PGSQL_DIAG_SEVERITY", PG_DIAG_SEVERITY, CONST_CS | CONST_PERSISTENT);
  1031. REGISTER_LONG_CONSTANT("PGSQL_DIAG_SQLSTATE", PG_DIAG_SQLSTATE, CONST_CS | CONST_PERSISTENT);
  1032. REGISTER_LONG_CONSTANT("PGSQL_DIAG_MESSAGE_PRIMARY", PG_DIAG_MESSAGE_PRIMARY, CONST_CS | CONST_PERSISTENT);
  1033. REGISTER_LONG_CONSTANT("PGSQL_DIAG_MESSAGE_DETAIL", PG_DIAG_MESSAGE_DETAIL, CONST_CS | CONST_PERSISTENT);
  1034. REGISTER_LONG_CONSTANT("PGSQL_DIAG_MESSAGE_HINT", PG_DIAG_MESSAGE_HINT, CONST_CS | CONST_PERSISTENT);
  1035. REGISTER_LONG_CONSTANT("PGSQL_DIAG_STATEMENT_POSITION", PG_DIAG_STATEMENT_POSITION, CONST_CS | CONST_PERSISTENT);
  1036. #ifdef PG_DIAG_INTERNAL_POSITION
  1037. REGISTER_LONG_CONSTANT("PGSQL_DIAG_INTERNAL_POSITION", PG_DIAG_INTERNAL_POSITION, CONST_CS | CONST_PERSISTENT);
  1038. #endif
  1039. #ifdef PG_DIAG_INTERNAL_QUERY
  1040. REGISTER_LONG_CONSTANT("PGSQL_DIAG_INTERNAL_QUERY", PG_DIAG_INTERNAL_QUERY, CONST_CS | CONST_PERSISTENT);
  1041. #endif
  1042. REGISTER_LONG_CONSTANT("PGSQL_DIAG_CONTEXT", PG_DIAG_CONTEXT, CONST_CS | CONST_PERSISTENT);
  1043. REGISTER_LONG_CONSTANT("PGSQL_DIAG_SOURCE_FILE", PG_DIAG_SOURCE_FILE, CONST_CS | CONST_PERSISTENT);
  1044. REGISTER_LONG_CONSTANT("PGSQL_DIAG_SOURCE_LINE", PG_DIAG_SOURCE_LINE, CONST_CS | CONST_PERSISTENT);
  1045. REGISTER_LONG_CONSTANT("PGSQL_DIAG_SOURCE_FUNCTION", PG_DIAG_SOURCE_FUNCTION, CONST_CS | CONST_PERSISTENT);
  1046. #ifdef PG_DIAG_SCHEMA_NAME
  1047. REGISTER_LONG_CONSTANT("PGSQL_DIAG_SCHEMA_NAME", PG_DIAG_SCHEMA_NAME, CONST_CS | CONST_PERSISTENT);
  1048. #endif
  1049. #ifdef PG_DIAG_TABLE_NAME
  1050. REGISTER_LONG_CONSTANT("PGSQL_DIAG_TABLE_NAME", PG_DIAG_TABLE_NAME, CONST_CS | CONST_PERSISTENT);
  1051. #endif
  1052. #ifdef PG_DIAG_COLUMN_NAME
  1053. REGISTER_LONG_CONSTANT("PGSQL_DIAG_COLUMN_NAME", PG_DIAG_COLUMN_NAME, CONST_CS | CONST_PERSISTENT);
  1054. #endif
  1055. #ifdef PG_DIAG_DATATYPE_NAME
  1056. REGISTER_LONG_CONSTANT("PGSQL_DIAG_DATATYPE_NAME", PG_DIAG_DATATYPE_NAME, CONST_CS | CONST_PERSISTENT);
  1057. #endif
  1058. #ifdef PG_DIAG_CONSTRAINT_NAME
  1059. REGISTER_LONG_CONSTANT("PGSQL_DIAG_CONSTRAINT_NAME", PG_DIAG_CONSTRAINT_NAME, CONST_CS | CONST_PERSISTENT);
  1060. #endif
  1061. #ifdef PG_DIAG_SEVERITY_NONLOCALIZED
  1062. REGISTER_LONG_CONSTANT("PGSQL_DIAG_SEVERITY_NONLOCALIZED", PG_DIAG_SEVERITY_NONLOCALIZED, CONST_CS | CONST_PERSISTENT);
  1063. #endif
  1064. #endif
  1065. /* pg_convert options */
  1066. REGISTER_LONG_CONSTANT("PGSQL_CONV_IGNORE_DEFAULT", PGSQL_CONV_IGNORE_DEFAULT, CONST_CS | CONST_PERSISTENT);
  1067. REGISTER_LONG_CONSTANT("PGSQL_CONV_FORCE_NULL", PGSQL_CONV_FORCE_NULL, CONST_CS | CONST_PERSISTENT);
  1068. REGISTER_LONG_CONSTANT("PGSQL_CONV_IGNORE_NOT_NULL", PGSQL_CONV_IGNORE_NOT_NULL, CONST_CS | CONST_PERSISTENT);
  1069. /* pg_insert/update/delete/select options */
  1070. REGISTER_LONG_CONSTANT("PGSQL_DML_ESCAPE", PGSQL_DML_ESCAPE, CONST_CS | CONST_PERSISTENT);
  1071. REGISTER_LONG_CONSTANT("PGSQL_DML_NO_CONV", PGSQL_DML_NO_CONV, CONST_CS | CONST_PERSISTENT);
  1072. REGISTER_LONG_CONSTANT("PGSQL_DML_EXEC", PGSQL_DML_EXEC, CONST_CS | CONST_PERSISTENT);
  1073. REGISTER_LONG_CONSTANT("PGSQL_DML_ASYNC", PGSQL_DML_ASYNC, CONST_CS | CONST_PERSISTENT);
  1074. REGISTER_LONG_CONSTANT("PGSQL_DML_STRING", PGSQL_DML_STRING, CONST_CS | CONST_PERSISTENT);
  1075. return SUCCESS;
  1076. }
  1077. /* }}} */
  1078. /* {{{ PHP_MSHUTDOWN_FUNCTION
  1079. */
  1080. PHP_MSHUTDOWN_FUNCTION(pgsql)
  1081. {
  1082. UNREGISTER_INI_ENTRIES();
  1083. zend_hash_destroy(&PGG(notices));
  1084. zend_hash_destroy(&PGG(hashes));
  1085. return SUCCESS;
  1086. }
  1087. /* }}} */
  1088. /* {{{ PHP_RINIT_FUNCTION
  1089. */
  1090. PHP_RINIT_FUNCTION(pgsql)
  1091. {
  1092. PGG(default_link) = NULL;
  1093. PGG(num_links) = PGG(num_persistent);
  1094. return SUCCESS;
  1095. }
  1096. /* }}} */
  1097. /* {{{ PHP_RSHUTDOWN_FUNCTION
  1098. */
  1099. PHP_RSHUTDOWN_FUNCTION(pgsql)
  1100. {
  1101. /* clean up notice messages */
  1102. zend_hash_clean(&PGG(notices));
  1103. zend_hash_clean(&PGG(hashes));
  1104. /* clean up persistent connection */
  1105. zend_hash_apply(&EG(persistent_list), (apply_func_t) _rollback_transactions);
  1106. return SUCCESS;
  1107. }
  1108. /* }}} */
  1109. /* {{{ PHP_MINFO_FUNCTION
  1110. */
  1111. PHP_MINFO_FUNCTION(pgsql)
  1112. {
  1113. char buf[256];
  1114. php_info_print_table_start();
  1115. php_info_print_table_header(2, "PostgreSQL Support", "enabled");
  1116. #if HAVE_PG_CONFIG_H
  1117. php_info_print_table_row(2, "PostgreSQL(libpq) Version", PG_VERSION);
  1118. php_info_print_table_row(2, "PostgreSQL(libpq) ", PG_VERSION_STR);
  1119. #ifdef HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT
  1120. php_info_print_table_row(2, "Multibyte character support", "enabled");
  1121. #else
  1122. php_info_print_table_row(2, "Multibyte character support", "disabled");
  1123. #endif
  1124. #if defined(USE_SSL) || defined(USE_OPENSSL)
  1125. php_info_print_table_row(2, "SSL support", "enabled");
  1126. #else
  1127. php_info_print_table_row(2, "SSL support", "disabled");
  1128. #endif
  1129. #endif /* HAVE_PG_CONFIG_H */
  1130. snprintf(buf, sizeof(buf), ZEND_LONG_FMT, PGG(num_persistent));
  1131. php_info_print_table_row(2, "Active Persistent Links", buf);
  1132. snprintf(buf, sizeof(buf), ZEND_LONG_FMT, PGG(num_links));
  1133. php_info_print_table_row(2, "Active Links", buf);
  1134. php_info_print_table_end();
  1135. DISPLAY_INI_ENTRIES();
  1136. }
  1137. /* }}} */
  1138. /* {{{ php_pgsql_do_connect
  1139. */
  1140. static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
  1141. {
  1142. char *host=NULL,*port=NULL,*options=NULL,*tty=NULL,*dbname=NULL,*connstring=NULL;
  1143. PGconn *pgsql;
  1144. smart_str str = {0};
  1145. zval *args;
  1146. uint32_t i;
  1147. int connect_type = 0;
  1148. PGresult *pg_result;
  1149. args = (zval *)safe_emalloc(ZEND_NUM_ARGS(), sizeof(zval), 0);
  1150. if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 5
  1151. || zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
  1152. efree(args);
  1153. WRONG_PARAM_COUNT;
  1154. }
  1155. smart_str_appends(&str, "pgsql");
  1156. for (i = 0; i < ZEND_NUM_ARGS(); i++) {
  1157. /* make sure that the PGSQL_CONNECT_FORCE_NEW bit is not part of the hash so that subsequent connections
  1158. * can re-use this connection. Bug #39979
  1159. */
  1160. if (i == 1 && ZEND_NUM_ARGS() == 2 && Z_TYPE(args[i]) == IS_LONG) {
  1161. if (Z_LVAL(args[1]) == PGSQL_CONNECT_FORCE_NEW) {
  1162. continue;
  1163. } else if (Z_LVAL(args[1]) & PGSQL_CONNECT_FORCE_NEW) {
  1164. smart_str_append_long(&str, Z_LVAL(args[1]) ^ PGSQL_CONNECT_FORCE_NEW);
  1165. }
  1166. }
  1167. ZVAL_STR(&args[i], zval_get_string(&args[i]));
  1168. smart_str_appendc(&str, '_');
  1169. smart_str_appendl(&str, Z_STRVAL(args[i]), Z_STRLEN(args[i]));
  1170. }
  1171. /* Exception thrown during a string conversion. */
  1172. if (EG(exception)) {
  1173. goto cleanup;
  1174. }
  1175. smart_str_0(&str);
  1176. if (ZEND_NUM_ARGS() == 1) { /* new style, using connection string */
  1177. connstring = Z_STRVAL(args[0]);
  1178. } else if (ZEND_NUM_ARGS() == 2 ) { /* Safe to add conntype_option, since 2 args was illegal */
  1179. connstring = Z_STRVAL(args[0]);
  1180. connect_type = (int)zval_get_long(&args[1]);
  1181. } else {
  1182. host = Z_STRVAL(args[0]);
  1183. port = Z_STRVAL(args[1]);
  1184. dbname = Z_STRVAL(args[ZEND_NUM_ARGS()-1]);
  1185. switch (ZEND_NUM_ARGS()) {
  1186. case 5:
  1187. tty = Z_STRVAL(args[3]);
  1188. /* fall through */
  1189. case 4:
  1190. options = Z_STRVAL(args[2]);
  1191. break;
  1192. }
  1193. }
  1194. if (persistent && PGG(allow_persistent)) {
  1195. zend_resource *le;
  1196. /* try to find if we already have this link in our persistent list */
  1197. if ((le = zend_hash_find_ptr(&EG(persistent_list), str.s)) == NULL) { /* we don't */
  1198. if (PGG(max_links) != -1 && PGG(num_links) >= PGG(max_links)) {
  1199. php_error_docref(NULL, E_WARNING,
  1200. "Cannot create new link. Too many open links (" ZEND_LONG_FMT ")", PGG(num_links));
  1201. goto err;
  1202. }
  1203. if (PGG(max_persistent) != -1 && PGG(num_persistent) >= PGG(max_persistent)) {
  1204. php_error_docref(NULL, E_WARNING,
  1205. "Cannot create new link. Too many open persistent links (" ZEND_LONG_FMT ")", PGG(num_persistent));
  1206. goto err;
  1207. }
  1208. /* create the link */
  1209. if (connstring) {
  1210. pgsql = PQconnectdb(connstring);
  1211. } else {
  1212. pgsql = PQsetdb(host, port, options, tty, dbname);
  1213. }
  1214. if (pgsql == NULL || PQstatus(pgsql) == CONNECTION_BAD) {
  1215. PHP_PQ_ERROR("Unable to connect to PostgreSQL server: %s", pgsql)
  1216. if (pgsql) {
  1217. PQfinish(pgsql);
  1218. }
  1219. goto err;
  1220. }
  1221. /* hash it up */
  1222. if (zend_register_persistent_resource(ZSTR_VAL(str.s), ZSTR_LEN(str.s), pgsql, le_plink) == NULL) {
  1223. goto err;
  1224. }
  1225. PGG(num_links)++;
  1226. PGG(num_persistent)++;
  1227. } else { /* we do */
  1228. if (le->type != le_plink) {
  1229. goto err;
  1230. }
  1231. /* ensure that the link did not die */
  1232. if (PGG(auto_reset_persistent) & 1) {
  1233. /* need to send & get something from backend to
  1234. make sure we catch CONNECTION_BAD every time */
  1235. PGresult *pg_result;
  1236. pg_result = PQexec(le->ptr, "select 1");
  1237. PQclear(pg_result);
  1238. }
  1239. if (PQstatus(le->ptr) == CONNECTION_BAD) { /* the link died */
  1240. if (le->ptr == NULL) {
  1241. if (connstring) {
  1242. le->ptr = PQconnectdb(connstring);
  1243. } else {
  1244. le->ptr = PQsetdb(host,port,options,tty,dbname);
  1245. }
  1246. }
  1247. else {
  1248. PQreset(le->ptr);
  1249. }
  1250. if (le->ptr == NULL || PQstatus(le->ptr) == CONNECTION_BAD) {
  1251. php_error_docref(NULL, E_WARNING,"PostgreSQL link lost, unable to reconnect");
  1252. zend_hash_del(&EG(persistent_list), str.s);
  1253. goto err;
  1254. }
  1255. }
  1256. pgsql = (PGconn *) le->ptr;
  1257. #if HAVE_PQPROTOCOLVERSION && HAVE_PQPARAMETERSTATUS
  1258. if (PQprotocolVersion(pgsql) >= 3 && atof(PQparameterStatus(pgsql, "server_version")) >= 7.2) {
  1259. #else
  1260. if (atof(PG_VERSION) >= 7.2) {
  1261. #endif
  1262. pg_result = PQexec(pgsql, "RESET ALL;");
  1263. PQclear(pg_result);
  1264. }
  1265. }
  1266. RETVAL_RES(zend_register_resource(pgsql, le_plink));
  1267. } else { /* Non persistent connection */
  1268. zend_resource *index_ptr, new_index_ptr;
  1269. /* first we check the hash for the hashed_details key. if it exists,
  1270. * it should point us to the right offset where the actual pgsql link sits.
  1271. * if it doesn't, open a new pgsql link, add it to the resource list,
  1272. * and add a pointer to it with hashed_details as the key.
  1273. */
  1274. if (!(connect_type & PGSQL_CONNECT_FORCE_NEW)
  1275. && (index_ptr = zend_hash_find_ptr(&EG(regular_list), str.s)) != NULL) {
  1276. zend_resource *link;
  1277. if (index_ptr->type != le_index_ptr) {
  1278. goto err;
  1279. }
  1280. link = (zend_resource *)index_ptr->ptr;
  1281. ZEND_ASSERT(link->ptr && (link->type == le_link || link->type == le_plink));
  1282. php_pgsql_set_default_link(link);
  1283. GC_ADDREF(link);
  1284. RETVAL_RES(link);
  1285. goto cleanup;
  1286. }
  1287. if (PGG(max_links) != -1 && PGG(num_links) >= PGG(max_links)) {
  1288. php_error_docref(NULL, E_WARNING, "Cannot create new link. Too many open links (" ZEND_LONG_FMT ")", PGG(num_links));
  1289. goto err;
  1290. }
  1291. /* Non-blocking connect */
  1292. if (connect_type & PGSQL_CONNECT_ASYNC) {
  1293. if (connstring) {
  1294. pgsql = PQconnectStart(connstring);
  1295. if (pgsql==NULL || PQstatus(pgsql)==CONNECTION_BAD) {
  1296. PHP_PQ_ERROR("Unable to connect to PostgreSQL server: %s", pgsql);
  1297. if (pgsql) {
  1298. PQfinish(pgsql);
  1299. }
  1300. goto err;
  1301. }
  1302. } else {
  1303. php_error_docref(NULL, E_WARNING, "Connection string required for async connections");
  1304. goto err;
  1305. }
  1306. } else {
  1307. if (connstring) {
  1308. pgsql = PQconnectdb(connstring);
  1309. } else {
  1310. pgsql = PQsetdb(host,port,options,tty,dbname);
  1311. }
  1312. if (pgsql==NULL || PQstatus(pgsql)==CONNECTION_BAD) {
  1313. PHP_PQ_ERROR("Unable to connect to PostgreSQL server: %s", pgsql);
  1314. if (pgsql) {
  1315. PQfinish(pgsql);
  1316. }
  1317. goto err;
  1318. }
  1319. }
  1320. /* add it to the list */
  1321. RETVAL_RES(zend_register_resource(pgsql, le_link));
  1322. /* add it to the hash */
  1323. new_index_ptr.ptr = (void *) Z_RES_P(return_value);
  1324. new_index_ptr.type = le_index_ptr;
  1325. zend_hash_update_mem(&EG(regular_list), str.s, (void *) &new_index_ptr, sizeof(zend_resource));
  1326. /* Keep track of link => hash mapping, so we can remove the hash entry from regular_list
  1327. * when the connection is closed. This uses the address of the connection rather than the
  1328. * zend_resource, because the resource destructor is passed a stack copy of the resource
  1329. * structure. */
  1330. {
  1331. zval tmp;
  1332. ZVAL_STR_COPY(&tmp, str.s);
  1333. zend_hash_index_update(&PGG(hashes), (uintptr_t) pgsql, &tmp);
  1334. }
  1335. PGG(num_links)++;
  1336. }
  1337. /* set notice processor */
  1338. if (! PGG(ignore_notices) && Z_TYPE_P(return_value) == IS_RESOURCE) {
  1339. PQsetNoticeProcessor(pgsql, _php_pgsql_notice_handler, (void*)(zend_uintptr_t)Z_RES_HANDLE_P(return_value));
  1340. }
  1341. php_pgsql_set_default_link(Z_RES_P(return_value));
  1342. cleanup:
  1343. for (i = 0; i < ZEND_NUM_ARGS(); i++) {
  1344. zval_ptr_dtor(&args[i]);
  1345. }
  1346. efree(args);
  1347. smart_str_free(&str);
  1348. return;
  1349. err:
  1350. for (i = 0; i < ZEND_NUM_ARGS(); i++) {
  1351. zval_ptr_dtor(&args[i]);
  1352. }
  1353. efree(args);
  1354. smart_str_free(&str);
  1355. RETURN_FALSE;
  1356. }
  1357. /* }}} */
  1358. /* {{{ proto resource pg_connect(string connection_string[, int connect_type] | [string host, string port [, string options [, string tty,]]] string database)
  1359. Open a PostgreSQL connection */
  1360. PHP_FUNCTION(pg_connect)
  1361. {
  1362. php_pgsql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
  1363. }
  1364. /* }}} */
  1365. /* {{{ proto resource pg_connect_poll(resource connection)
  1366. Poll the status of an in-progress async PostgreSQL connection attempt*/
  1367. PHP_FUNCTION(pg_connect_poll)
  1368. {
  1369. zval *pgsql_link;
  1370. PGconn *pgsql;
  1371. int ret;
  1372. if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &pgsql_link) == FAILURE) {
  1373. RETURN_THROWS();
  1374. }
  1375. if ((pgsql = (PGconn *)zend_fetch_resource2(Z_RES_P(pgsql_link), "…

Large files files are truncated, but you can click here to view the full file