1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 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: Zeev Suraski <zeev@zend.com> |
16 : | Jouni Ahto <jouni.ahto@exdec.fi> |
17 : | Yasuo Ohgaki <yohgaki@php.net> |
18 : | Youichi Iwakiri <yiwakiri@st.rim.or.jp> (pg_copy_*) |
19 : | Chris Kings-Lynne <chriskl@php.net> (v3 protocol) |
20 : +----------------------------------------------------------------------+
21 : */
22 :
23 : /* $Id: pgsql.c 290146 2009-11-02 13:33:24Z iliaa $ */
24 :
25 : #include <stdlib.h>
26 :
27 : #define PHP_PGSQL_PRIVATE 1
28 :
29 : #ifdef HAVE_CONFIG_H
30 : #include "config.h"
31 : #endif
32 :
33 : #define SMART_STR_PREALLOC 512
34 :
35 : #include "php.h"
36 : #include "php_ini.h"
37 : #include "ext/standard/php_standard.h"
38 : #include "ext/standard/php_smart_str.h"
39 : #include "ext/ereg/php_regex.h"
40 :
41 : #undef PACKAGE_BUGREPORT
42 : #undef PACKAGE_NAME
43 : #undef PACKAGE_STRING
44 : #undef PACKAGE_TARNAME
45 : #undef PACKAGE_VERSION
46 : #include "php_pgsql.h"
47 : #include "php_globals.h"
48 : #include "zend_exceptions.h"
49 :
50 : #if HAVE_PGSQL
51 :
52 : #ifndef InvalidOid
53 : #define InvalidOid ((Oid) 0)
54 : #endif
55 :
56 : #define PGSQL_ASSOC 1<<0
57 : #define PGSQL_NUM 1<<1
58 : #define PGSQL_BOTH (PGSQL_ASSOC|PGSQL_NUM)
59 :
60 : #define PGSQL_STATUS_LONG 1
61 : #define PGSQL_STATUS_STRING 2
62 :
63 : #define PGSQL_MAX_LENGTH_OF_LONG 30
64 : #define PGSQL_MAX_LENGTH_OF_DOUBLE 60
65 :
66 : #define PGSQL_RETURN_OID(oid) do { \
67 : if (oid > LONG_MAX) { \
68 : smart_str s = {0}; \
69 : smart_str_append_unsigned(&s, oid); \
70 : smart_str_0(&s); \
71 : RETURN_STRINGL(s.c, s.len, 0); \
72 : } \
73 : RETURN_LONG((long)oid); \
74 : } while(0)
75 :
76 :
77 : #if HAVE_PQSETNONBLOCKING
78 : #define PQ_SETNONBLOCKING(pg_link, flag) PQsetnonblocking(pg_link, flag)
79 : #else
80 : #define PQ_SETNONBLOCKING(pg_link, flag) 0
81 : #endif
82 :
83 : #define CHECK_DEFAULT_LINK(x) if ((x) == -1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "No PostgreSQL link opened yet"); }
84 :
85 : #ifndef HAVE_PQFREEMEM
86 : #define PQfreemem free
87 : #endif
88 :
89 : ZEND_DECLARE_MODULE_GLOBALS(pgsql)
90 : static PHP_GINIT_FUNCTION(pgsql);
91 :
92 : /* {{{ arginfo */
93 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_connect, 0, 0, 1)
94 : ZEND_ARG_INFO(0, connection_string)
95 : ZEND_ARG_INFO(0, connect_type)
96 : ZEND_ARG_INFO(0, host)
97 : ZEND_ARG_INFO(0, port)
98 : ZEND_ARG_INFO(0, options)
99 : ZEND_ARG_INFO(0, tty)
100 : ZEND_ARG_INFO(0, database)
101 : ZEND_END_ARG_INFO()
102 :
103 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_pconnect, 0, 0, 1)
104 : ZEND_ARG_INFO(0, connection_string)
105 : ZEND_ARG_INFO(0, host)
106 : ZEND_ARG_INFO(0, port)
107 : ZEND_ARG_INFO(0, options)
108 : ZEND_ARG_INFO(0, tty)
109 : ZEND_ARG_INFO(0, database)
110 : ZEND_END_ARG_INFO()
111 :
112 : #if HAVE_PQPARAMETERSTATUS
113 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_parameter_status, 0, 0, 1)
114 : ZEND_ARG_INFO(0, connection)
115 : ZEND_ARG_INFO(0, param_name)
116 : ZEND_END_ARG_INFO()
117 : #endif
118 :
119 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_close, 0, 0, 0)
120 : ZEND_ARG_INFO(0, connection)
121 : ZEND_END_ARG_INFO()
122 :
123 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_dbname, 0, 0, 0)
124 : ZEND_ARG_INFO(0, connection)
125 : ZEND_END_ARG_INFO()
126 :
127 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_last_error, 0, 0, 0)
128 : ZEND_ARG_INFO(0, connection)
129 : ZEND_END_ARG_INFO()
130 :
131 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_options, 0, 0, 0)
132 : ZEND_ARG_INFO(0, connection)
133 : ZEND_END_ARG_INFO()
134 :
135 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_port, 0, 0, 0)
136 : ZEND_ARG_INFO(0, connection)
137 : ZEND_END_ARG_INFO()
138 :
139 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_tty, 0, 0, 0)
140 : ZEND_ARG_INFO(0, connection)
141 : ZEND_END_ARG_INFO()
142 :
143 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_host, 0, 0, 0)
144 : ZEND_ARG_INFO(0, connection)
145 : ZEND_END_ARG_INFO()
146 :
147 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_version, 0, 0, 0)
148 : ZEND_ARG_INFO(0, connection)
149 : ZEND_END_ARG_INFO()
150 :
151 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_ping, 0, 0, 0)
152 : ZEND_ARG_INFO(0, connection)
153 : ZEND_END_ARG_INFO()
154 :
155 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_query, 0, 0, 0)
156 : ZEND_ARG_INFO(0, connection)
157 : ZEND_ARG_INFO(0, query)
158 : ZEND_END_ARG_INFO()
159 :
160 : #if HAVE_PQEXECPARAMS
161 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_query_params, 0, 0, 0)
162 : ZEND_ARG_INFO(0, connection)
163 : ZEND_ARG_INFO(0, query)
164 : ZEND_ARG_INFO(0, params)
165 : ZEND_END_ARG_INFO()
166 : #endif
167 :
168 : #if HAVE_PQPREPARE
169 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_prepare, 0, 0, 0)
170 : ZEND_ARG_INFO(0, connection)
171 : ZEND_ARG_INFO(0, stmtname)
172 : ZEND_ARG_INFO(0, query)
173 : ZEND_END_ARG_INFO()
174 : #endif
175 :
176 : #if HAVE_PQEXECPREPARED
177 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_execute, 0, 0, 0)
178 : ZEND_ARG_INFO(0, connection)
179 : ZEND_ARG_INFO(0, stmtname)
180 : ZEND_ARG_INFO(0, params)
181 : ZEND_END_ARG_INFO()
182 : #endif
183 :
184 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_num_rows, 0, 0, 1)
185 : ZEND_ARG_INFO(0, result)
186 : ZEND_END_ARG_INFO()
187 :
188 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_num_fields, 0, 0, 1)
189 : ZEND_ARG_INFO(0, result)
190 : ZEND_END_ARG_INFO()
191 :
192 : #if HAVE_PQCMDTUPLES
193 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_affected_rows, 0, 0, 1)
194 : ZEND_ARG_INFO(0, result)
195 : ZEND_END_ARG_INFO()
196 : #endif
197 :
198 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_last_notice, 0, 0, 1)
199 : ZEND_ARG_INFO(0, connection)
200 : ZEND_END_ARG_INFO()
201 :
202 : #ifdef HAVE_PQFTABLE
203 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_table, 0, 0, 2)
204 : ZEND_ARG_INFO(0, result)
205 : ZEND_ARG_INFO(0, field_number)
206 : ZEND_ARG_INFO(0, oid_only)
207 : ZEND_END_ARG_INFO()
208 : #endif
209 :
210 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_name, 0, 0, 2)
211 : ZEND_ARG_INFO(0, result)
212 : ZEND_ARG_INFO(0, field_number)
213 : ZEND_END_ARG_INFO()
214 :
215 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_size, 0, 0, 2)
216 : ZEND_ARG_INFO(0, result)
217 : ZEND_ARG_INFO(0, field_number)
218 : ZEND_END_ARG_INFO()
219 :
220 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_type, 0, 0, 2)
221 : ZEND_ARG_INFO(0, result)
222 : ZEND_ARG_INFO(0, field_number)
223 : ZEND_END_ARG_INFO()
224 :
225 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_type_oid, 0, 0, 2)
226 : ZEND_ARG_INFO(0, result)
227 : ZEND_ARG_INFO(0, field_number)
228 : ZEND_END_ARG_INFO()
229 :
230 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_num, 0, 0, 2)
231 : ZEND_ARG_INFO(0, result)
232 : ZEND_ARG_INFO(0, field_name)
233 : ZEND_END_ARG_INFO()
234 :
235 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_result, 0, 0, 1)
236 : ZEND_ARG_INFO(0, result)
237 : ZEND_ARG_INFO(0, row_number)
238 : ZEND_ARG_INFO(0, field_name)
239 : ZEND_END_ARG_INFO()
240 :
241 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_row, 0, 0, 1)
242 : ZEND_ARG_INFO(0, result)
243 : ZEND_ARG_INFO(0, row)
244 : ZEND_ARG_INFO(0, result_type)
245 : ZEND_END_ARG_INFO()
246 :
247 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_assoc, 0, 0, 1)
248 : ZEND_ARG_INFO(0, result)
249 : ZEND_ARG_INFO(0, row)
250 : ZEND_END_ARG_INFO()
251 :
252 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_array, 0, 0, 1)
253 : ZEND_ARG_INFO(0, result)
254 : ZEND_ARG_INFO(0, row)
255 : ZEND_ARG_INFO(0, result_type)
256 : ZEND_END_ARG_INFO()
257 :
258 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_object, 0, 0, 1)
259 : ZEND_ARG_INFO(0, result)
260 : ZEND_ARG_INFO(0, row)
261 : ZEND_ARG_INFO(0, class_name)
262 : ZEND_ARG_INFO(0, l)
263 : ZEND_ARG_INFO(0, ctor_params)
264 : ZEND_END_ARG_INFO()
265 :
266 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_all, 0, 0, 1)
267 : ZEND_ARG_INFO(0, result)
268 : ZEND_END_ARG_INFO()
269 :
270 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_fetch_all_columns, 0, 0, 1)
271 : ZEND_ARG_INFO(0, result)
272 : ZEND_ARG_INFO(0, column_number)
273 : ZEND_END_ARG_INFO()
274 :
275 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_result_seek, 0, 0, 2)
276 : ZEND_ARG_INFO(0, result)
277 : ZEND_ARG_INFO(0, offset)
278 : ZEND_END_ARG_INFO()
279 :
280 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_prtlen, 0, 0, 1)
281 : ZEND_ARG_INFO(0, result)
282 : ZEND_ARG_INFO(0, row)
283 : ZEND_ARG_INFO(0, field_name_or_number)
284 : ZEND_END_ARG_INFO()
285 :
286 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_field_is_null, 0, 0, 1)
287 : ZEND_ARG_INFO(0, result)
288 : ZEND_ARG_INFO(0, row)
289 : ZEND_ARG_INFO(0, field_name_or_number)
290 : ZEND_END_ARG_INFO()
291 :
292 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_free_result, 0, 0, 1)
293 : ZEND_ARG_INFO(0, result)
294 : ZEND_END_ARG_INFO()
295 :
296 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_last_oid, 0, 0, 1)
297 : ZEND_ARG_INFO(0, result)
298 : ZEND_END_ARG_INFO()
299 :
300 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_trace, 0, 0, 1)
301 : ZEND_ARG_INFO(0, filename)
302 : ZEND_ARG_INFO(0, mode)
303 : ZEND_ARG_INFO(0, connection)
304 : ZEND_END_ARG_INFO()
305 :
306 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_untrace, 0, 0, 0)
307 : ZEND_ARG_INFO(0, connection)
308 : ZEND_END_ARG_INFO()
309 :
310 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_create, 0, 0, 0)
311 : ZEND_ARG_INFO(0, connection)
312 : ZEND_ARG_INFO(0, large_object_id)
313 : ZEND_END_ARG_INFO()
314 :
315 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_unlink, 0, 0, 0)
316 : ZEND_ARG_INFO(0, connection)
317 : ZEND_ARG_INFO(0, large_object_oid)
318 : ZEND_END_ARG_INFO()
319 :
320 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_open, 0, 0, 0)
321 : ZEND_ARG_INFO(0, connection)
322 : ZEND_ARG_INFO(0, large_object_oid)
323 : ZEND_ARG_INFO(0, mode)
324 : ZEND_END_ARG_INFO()
325 :
326 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_close, 0, 0, 1)
327 : ZEND_ARG_INFO(0, large_object)
328 : ZEND_END_ARG_INFO()
329 :
330 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_read, 0, 0, 1)
331 : ZEND_ARG_INFO(0, large_object)
332 : ZEND_ARG_INFO(0, len)
333 : ZEND_END_ARG_INFO()
334 :
335 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_write, 0, 0, 2)
336 : ZEND_ARG_INFO(0, large_object)
337 : ZEND_ARG_INFO(0, buf)
338 : ZEND_ARG_INFO(0, len)
339 : ZEND_END_ARG_INFO()
340 :
341 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_read_all, 0, 0, 1)
342 : ZEND_ARG_INFO(0, large_object)
343 : ZEND_END_ARG_INFO()
344 :
345 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_import, 0, 0, 0)
346 : ZEND_ARG_INFO(0, connection)
347 : ZEND_ARG_INFO(0, filename)
348 : ZEND_ARG_INFO(0, large_object_oid)
349 : ZEND_END_ARG_INFO()
350 :
351 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_export, 0, 0, 0)
352 : ZEND_ARG_INFO(0, connection)
353 : ZEND_ARG_INFO(0, objoid)
354 : ZEND_ARG_INFO(0, filename)
355 : ZEND_END_ARG_INFO()
356 :
357 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_seek, 0, 0, 2)
358 : ZEND_ARG_INFO(0, large_object)
359 : ZEND_ARG_INFO(0, offset)
360 : ZEND_ARG_INFO(0, whence)
361 : ZEND_END_ARG_INFO()
362 :
363 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_lo_tell, 0, 0, 1)
364 : ZEND_ARG_INFO(0, large_object)
365 : ZEND_END_ARG_INFO()
366 :
367 : #if HAVE_PQSETERRORVERBOSITY
368 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_set_error_verbosity, 0, 0, 0)
369 : ZEND_ARG_INFO(0, connection)
370 : ZEND_ARG_INFO(0, verbosity)
371 : ZEND_END_ARG_INFO()
372 : #endif
373 :
374 : #if HAVE_PQCLIENTENCODING
375 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_set_client_encoding, 0, 0, 0)
376 : ZEND_ARG_INFO(0, connection)
377 : ZEND_ARG_INFO(0, encoding)
378 : ZEND_END_ARG_INFO()
379 :
380 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_client_encoding, 0, 0, 0)
381 : ZEND_ARG_INFO(0, connection)
382 : ZEND_END_ARG_INFO()
383 : #endif
384 :
385 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_end_copy, 0, 0, 0)
386 : ZEND_ARG_INFO(0, connection)
387 : ZEND_END_ARG_INFO()
388 :
389 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_put_line, 0, 0, 0)
390 : ZEND_ARG_INFO(0, connection)
391 : ZEND_ARG_INFO(0, query)
392 : ZEND_END_ARG_INFO()
393 :
394 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_copy_to, 0, 0, 2)
395 : ZEND_ARG_INFO(0, connection)
396 : ZEND_ARG_INFO(0, table_name)
397 : ZEND_ARG_INFO(0, delimiter)
398 : ZEND_ARG_INFO(0, null_as)
399 : ZEND_END_ARG_INFO()
400 :
401 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_copy_from, 0, 0, 3)
402 : ZEND_ARG_INFO(0, connection)
403 : ZEND_ARG_INFO(0, table_name)
404 : ZEND_ARG_INFO(0, rows)
405 : ZEND_ARG_INFO(0, delimiter)
406 : ZEND_ARG_INFO(0, null_as)
407 : ZEND_END_ARG_INFO()
408 :
409 : #if HAVE_PQESCAPE
410 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_escape_string, 0, 0, 0)
411 : ZEND_ARG_INFO(0, connection)
412 : ZEND_ARG_INFO(0, data)
413 : ZEND_END_ARG_INFO()
414 :
415 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_escape_bytea, 0, 0, 0)
416 : ZEND_ARG_INFO(0, connection)
417 : ZEND_ARG_INFO(0, data)
418 : ZEND_END_ARG_INFO()
419 :
420 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_unescape_bytea, 0, 0, 1)
421 : ZEND_ARG_INFO(0, data)
422 : ZEND_END_ARG_INFO()
423 : #endif
424 :
425 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_result_error, 0, 0, 1)
426 : ZEND_ARG_INFO(0, result)
427 : ZEND_END_ARG_INFO()
428 :
429 : #if HAVE_PQRESULTERRORFIELD
430 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_result_error_field, 0, 0, 2)
431 : ZEND_ARG_INFO(0, result)
432 : ZEND_ARG_INFO(0, fieldcode)
433 : ZEND_END_ARG_INFO()
434 : #endif
435 :
436 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_connection_status, 0, 0, 1)
437 : ZEND_ARG_INFO(0, connnection)
438 : ZEND_END_ARG_INFO()
439 :
440 : #if HAVE_PGTRANSACTIONSTATUS
441 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_transaction_status, 0, 0, 1)
442 : ZEND_ARG_INFO(0, connnection)
443 : ZEND_END_ARG_INFO()
444 : #endif
445 :
446 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_connection_reset, 0, 0, 1)
447 : ZEND_ARG_INFO(0, connection)
448 : ZEND_END_ARG_INFO()
449 :
450 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_cancel_query, 0, 0, 1)
451 : ZEND_ARG_INFO(0, connection)
452 : ZEND_END_ARG_INFO()
453 :
454 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_connection_busy, 0, 0, 1)
455 : ZEND_ARG_INFO(0, connection)
456 : ZEND_END_ARG_INFO()
457 :
458 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_send_query, 0, 0, 2)
459 : ZEND_ARG_INFO(0, connection)
460 : ZEND_ARG_INFO(0, query)
461 : ZEND_END_ARG_INFO()
462 :
463 : #if HAVE_PQSENDQUERYPARAMS
464 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_send_query_params, 0, 0, 3)
465 : ZEND_ARG_INFO(0, connection)
466 : ZEND_ARG_INFO(0, query)
467 : ZEND_ARG_INFO(0, params)
468 : ZEND_END_ARG_INFO()
469 : #endif
470 :
471 : #if HAVE_PQSENDPREPARE
472 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_send_prepare, 0, 0, 3)
473 : ZEND_ARG_INFO(0, connection)
474 : ZEND_ARG_INFO(0, stmtname)
475 : ZEND_ARG_INFO(0, query)
476 : ZEND_END_ARG_INFO()
477 : #endif
478 :
479 : #if HAVE_PQSENDQUERYPREPARED
480 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_send_execute, 0, 0, 3)
481 : ZEND_ARG_INFO(0, connection)
482 : ZEND_ARG_INFO(0, stmtname)
483 : ZEND_ARG_INFO(0, params)
484 : ZEND_END_ARG_INFO()
485 : #endif
486 :
487 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_get_result, 0, 0, 1)
488 : ZEND_ARG_INFO(0, connection)
489 : ZEND_END_ARG_INFO()
490 :
491 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_result_status, 0, 0, 1)
492 : ZEND_ARG_INFO(0, result)
493 : ZEND_ARG_INFO(0, result_type)
494 : ZEND_END_ARG_INFO()
495 :
496 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_get_notify, 0, 0, 0)
497 : ZEND_ARG_INFO(0, connection)
498 : ZEND_ARG_INFO(0, e)
499 : ZEND_END_ARG_INFO()
500 :
501 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_get_pid, 0, 0, 0)
502 : ZEND_ARG_INFO(0, connection)
503 : ZEND_END_ARG_INFO()
504 :
505 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_meta_data, 0, 0, 2)
506 : ZEND_ARG_INFO(0, db)
507 : ZEND_ARG_INFO(0, table)
508 : ZEND_END_ARG_INFO()
509 :
510 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_convert, 0, 0, 3)
511 : ZEND_ARG_INFO(0, db)
512 : ZEND_ARG_INFO(0, table)
513 : ZEND_ARG_INFO(0, values)
514 : ZEND_ARG_INFO(0, options)
515 : ZEND_END_ARG_INFO()
516 :
517 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_insert, 0, 0, 3)
518 : ZEND_ARG_INFO(0, db)
519 : ZEND_ARG_INFO(0, table)
520 : ZEND_ARG_INFO(0, values)
521 : ZEND_ARG_INFO(0, options)
522 : ZEND_END_ARG_INFO()
523 :
524 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_update, 0, 0, 4)
525 : ZEND_ARG_INFO(0, db)
526 : ZEND_ARG_INFO(0, table)
527 : ZEND_ARG_INFO(0, fields)
528 : ZEND_ARG_INFO(0, ids)
529 : ZEND_ARG_INFO(0, options)
530 : ZEND_END_ARG_INFO()
531 :
532 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_delete, 0, 0, 3)
533 : ZEND_ARG_INFO(0, db)
534 : ZEND_ARG_INFO(0, table)
535 : ZEND_ARG_INFO(0, ids)
536 : ZEND_ARG_INFO(0, options)
537 : ZEND_END_ARG_INFO()
538 :
539 : ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_select, 0, 0, 3)
540 : ZEND_ARG_INFO(0, db)
541 : ZEND_ARG_INFO(0, table)
542 : ZEND_ARG_INFO(0, ids)
543 : ZEND_ARG_INFO(0, options)
544 : ZEND_END_ARG_INFO()
545 : /* }}} */
546 :
547 : /* {{{ pgsql_functions[]
548 : */
549 : const zend_function_entry pgsql_functions[] = {
550 : /* connection functions */
551 : PHP_FE(pg_connect, arginfo_pg_connect)
552 : PHP_FE(pg_pconnect, arginfo_pg_pconnect)
553 : PHP_FE(pg_close, arginfo_pg_close)
554 : PHP_FE(pg_connection_status, arginfo_pg_connection_status)
555 : PHP_FE(pg_connection_busy, arginfo_pg_connection_busy)
556 : PHP_FE(pg_connection_reset, arginfo_pg_connection_reset)
557 : PHP_FE(pg_host, arginfo_pg_host)
558 : PHP_FE(pg_dbname, arginfo_pg_dbname)
559 : PHP_FE(pg_port, arginfo_pg_port)
560 : PHP_FE(pg_tty, arginfo_pg_tty)
561 : PHP_FE(pg_options, arginfo_pg_options)
562 : PHP_FE(pg_version, arginfo_pg_version)
563 : PHP_FE(pg_ping, arginfo_pg_ping)
564 : #if HAVE_PQPARAMETERSTATUS
565 : PHP_FE(pg_parameter_status, arginfo_pg_parameter_status)
566 : #endif
567 : #if HAVE_PGTRANSACTIONSTATUS
568 : PHP_FE(pg_transaction_status, arginfo_pg_transaction_status)
569 : #endif
570 : /* query functions */
571 : PHP_FE(pg_query, arginfo_pg_query)
572 : #if HAVE_PQEXECPARAMS
573 : PHP_FE(pg_query_params, arginfo_pg_query_params)
574 : #endif
575 : #if HAVE_PQPREPARE
576 : PHP_FE(pg_prepare, arginfo_pg_prepare)
577 : #endif
578 : #if HAVE_PQEXECPREPARED
579 : PHP_FE(pg_execute, arginfo_pg_execute)
580 : #endif
581 : PHP_FE(pg_send_query, arginfo_pg_send_query)
582 : #if HAVE_PQSENDQUERYPARAMS
583 : PHP_FE(pg_send_query_params, arginfo_pg_send_query_params)
584 : #endif
585 : #if HAVE_PQSENDPREPARE
586 : PHP_FE(pg_send_prepare, arginfo_pg_send_prepare)
587 : #endif
588 : #if HAVE_PQSENDQUERYPREPARED
589 : PHP_FE(pg_send_execute, arginfo_pg_send_execute)
590 : #endif
591 : PHP_FE(pg_cancel_query, arginfo_pg_cancel_query)
592 : /* result functions */
593 : PHP_FE(pg_fetch_result, arginfo_pg_fetch_result)
594 : PHP_FE(pg_fetch_row, arginfo_pg_fetch_row)
595 : PHP_FE(pg_fetch_assoc, arginfo_pg_fetch_assoc)
596 : PHP_FE(pg_fetch_array, arginfo_pg_fetch_array)
597 : PHP_FE(pg_fetch_object, arginfo_pg_fetch_object)
598 : PHP_FE(pg_fetch_all, arginfo_pg_fetch_all)
599 : PHP_FE(pg_fetch_all_columns, arginfo_pg_fetch_all_columns)
600 : #if HAVE_PQCMDTUPLES
601 : PHP_FE(pg_affected_rows,arginfo_pg_affected_rows)
602 : #endif
603 : PHP_FE(pg_get_result, arginfo_pg_get_result)
604 : PHP_FE(pg_result_seek, arginfo_pg_result_seek)
605 : PHP_FE(pg_result_status,arginfo_pg_result_status)
606 : PHP_FE(pg_free_result, arginfo_pg_free_result)
607 : PHP_FE(pg_last_oid, arginfo_pg_last_oid)
608 : PHP_FE(pg_num_rows, arginfo_pg_num_rows)
609 : PHP_FE(pg_num_fields, arginfo_pg_num_fields)
610 : PHP_FE(pg_field_name, arginfo_pg_field_name)
611 : PHP_FE(pg_field_num, arginfo_pg_field_num)
612 : PHP_FE(pg_field_size, arginfo_pg_field_size)
613 : PHP_FE(pg_field_type, arginfo_pg_field_type)
614 : PHP_FE(pg_field_type_oid, arginfo_pg_field_type_oid)
615 : PHP_FE(pg_field_prtlen, arginfo_pg_field_prtlen)
616 : PHP_FE(pg_field_is_null,arginfo_pg_field_is_null)
617 : #ifdef HAVE_PQFTABLE
618 : PHP_FE(pg_field_table, arginfo_pg_field_table)
619 : #endif
620 : /* async message function */
621 : PHP_FE(pg_get_notify, arginfo_pg_get_notify)
622 : PHP_FE(pg_get_pid, arginfo_pg_get_pid)
623 : /* error message functions */
624 : PHP_FE(pg_result_error, arginfo_pg_result_error)
625 : #if HAVE_PQRESULTERRORFIELD
626 : PHP_FE(pg_result_error_field, arginfo_pg_result_error_field)
627 : #endif
628 : PHP_FE(pg_last_error, arginfo_pg_last_error)
629 : PHP_FE(pg_last_notice, arginfo_pg_last_notice)
630 : /* copy functions */
631 : PHP_FE(pg_put_line, arginfo_pg_put_line)
632 : PHP_FE(pg_end_copy, arginfo_pg_end_copy)
633 : PHP_FE(pg_copy_to, arginfo_pg_copy_to)
634 : PHP_FE(pg_copy_from, arginfo_pg_copy_from)
635 : /* debug functions */
636 : PHP_FE(pg_trace, arginfo_pg_trace)
637 : PHP_FE(pg_untrace, arginfo_pg_untrace)
638 : /* large object functions */
639 : PHP_FE(pg_lo_create, arginfo_pg_lo_create)
640 : PHP_FE(pg_lo_unlink, arginfo_pg_lo_unlink)
641 : PHP_FE(pg_lo_open, arginfo_pg_lo_open)
642 : PHP_FE(pg_lo_close, arginfo_pg_lo_close)
643 : PHP_FE(pg_lo_read, arginfo_pg_lo_read)
644 : PHP_FE(pg_lo_write, arginfo_pg_lo_write)
645 : PHP_FE(pg_lo_read_all, arginfo_pg_lo_read_all)
646 : PHP_FE(pg_lo_import, arginfo_pg_lo_import)
647 : PHP_FE(pg_lo_export, arginfo_pg_lo_export)
648 : PHP_FE(pg_lo_seek, arginfo_pg_lo_seek)
649 : PHP_FE(pg_lo_tell, arginfo_pg_lo_tell)
650 : /* utility functions */
651 : #if HAVE_PQESCAPE
652 : PHP_FE(pg_escape_string, arginfo_pg_escape_string)
653 : PHP_FE(pg_escape_bytea, arginfo_pg_escape_bytea)
654 : PHP_FE(pg_unescape_bytea, arginfo_pg_unescape_bytea)
655 : #endif
656 : #if HAVE_PQSETERRORVERBOSITY
657 : PHP_FE(pg_set_error_verbosity, arginfo_pg_set_error_verbosity)
658 : #endif
659 : #if HAVE_PQCLIENTENCODING
660 : PHP_FE(pg_client_encoding, arginfo_pg_client_encoding)
661 : PHP_FE(pg_set_client_encoding, arginfo_pg_set_client_encoding)
662 : #endif
663 : /* misc function */
664 : PHP_FE(pg_meta_data, arginfo_pg_meta_data)
665 : PHP_FE(pg_convert, arginfo_pg_convert)
666 : PHP_FE(pg_insert, arginfo_pg_insert)
667 : PHP_FE(pg_update, arginfo_pg_update)
668 : PHP_FE(pg_delete, arginfo_pg_delete)
669 : PHP_FE(pg_select, arginfo_pg_select)
670 : /* aliases for downwards compatibility */
671 : PHP_FALIAS(pg_exec, pg_query, arginfo_pg_query)
672 : PHP_FALIAS(pg_getlastoid, pg_last_oid, arginfo_pg_last_oid)
673 : #if HAVE_PQCMDTUPLES
674 : PHP_FALIAS(pg_cmdtuples, pg_affected_rows, arginfo_pg_affected_rows)
675 : #endif
676 : PHP_FALIAS(pg_errormessage, pg_last_error, arginfo_pg_last_error)
677 : PHP_FALIAS(pg_numrows, pg_num_rows, arginfo_pg_num_rows)
678 : PHP_FALIAS(pg_numfields, pg_num_fields, arginfo_pg_num_fields)
679 : PHP_FALIAS(pg_fieldname, pg_field_name, arginfo_pg_field_name)
680 : PHP_FALIAS(pg_fieldsize, pg_field_size, arginfo_pg_field_size)
681 : PHP_FALIAS(pg_fieldtype, pg_field_type, arginfo_pg_field_type)
682 : PHP_FALIAS(pg_fieldnum, pg_field_num, arginfo_pg_field_num)
683 : PHP_FALIAS(pg_fieldprtlen, pg_field_prtlen, arginfo_pg_field_prtlen)
684 : PHP_FALIAS(pg_fieldisnull, pg_field_is_null, arginfo_pg_field_is_null)
685 : PHP_FALIAS(pg_freeresult, pg_free_result, arginfo_pg_free_result)
686 : PHP_FALIAS(pg_result, pg_fetch_result, arginfo_pg_get_result)
687 : PHP_FALIAS(pg_loreadall, pg_lo_read_all, arginfo_pg_lo_read_all)
688 : PHP_FALIAS(pg_locreate, pg_lo_create, arginfo_pg_lo_create)
689 : PHP_FALIAS(pg_lounlink, pg_lo_unlink, arginfo_pg_lo_unlink)
690 : PHP_FALIAS(pg_loopen, pg_lo_open, arginfo_pg_lo_open)
691 : PHP_FALIAS(pg_loclose, pg_lo_close, arginfo_pg_lo_close)
692 : PHP_FALIAS(pg_loread, pg_lo_read, arginfo_pg_lo_read)
693 : PHP_FALIAS(pg_lowrite, pg_lo_write, arginfo_pg_lo_write)
694 : PHP_FALIAS(pg_loimport, pg_lo_import, arginfo_pg_lo_import)
695 : PHP_FALIAS(pg_loexport, pg_lo_export, arginfo_pg_lo_export)
696 : #if HAVE_PQCLIENTENCODING
697 : PHP_FALIAS(pg_clientencoding, pg_client_encoding, arginfo_pg_client_encoding)
698 : PHP_FALIAS(pg_setclientencoding, pg_set_client_encoding, arginfo_pg_set_client_encoding)
699 : #endif
700 : {NULL, NULL, NULL}
701 : };
702 : /* }}} */
703 :
704 : /* {{{ pgsql_module_entry
705 : */
706 : zend_module_entry pgsql_module_entry = {
707 : STANDARD_MODULE_HEADER,
708 : "pgsql",
709 : pgsql_functions,
710 : PHP_MINIT(pgsql),
711 : PHP_MSHUTDOWN(pgsql),
712 : PHP_RINIT(pgsql),
713 : PHP_RSHUTDOWN(pgsql),
714 : PHP_MINFO(pgsql),
715 : NO_VERSION_YET,
716 : PHP_MODULE_GLOBALS(pgsql),
717 : PHP_GINIT(pgsql),
718 : NULL,
719 : NULL,
720 : STANDARD_MODULE_PROPERTIES_EX
721 : };
722 : /* }}} */
723 :
724 : #ifdef COMPILE_DL_PGSQL
725 : ZEND_GET_MODULE(pgsql)
726 : #endif
727 :
728 : static int le_link, le_plink, le_result, le_lofp, le_string;
729 :
730 : /* {{{ _php_pgsql_trim_message */
731 : static char * _php_pgsql_trim_message(const char *message, int *len)
732 14 : {
733 14 : register int i = strlen(message)-1;
734 :
735 14 : if (i>1 && (message[i-1] == '\r' || message[i-1] == '\n') && message[i] == '.') {
736 0 : --i;
737 : }
738 40 : while (i>0 && (message[i] == '\r' || message[i] == '\n')) {
739 12 : --i;
740 : }
741 14 : ++i;
742 14 : if (len) {
743 7 : *len = i;
744 : }
745 14 : return estrndup(message, i);
746 : }
747 : /* }}} */
748 :
749 : /* {{{ _php_pgsql_trim_result */
750 : static inline char * _php_pgsql_trim_result(PGconn * pgsql, char **buf)
751 2 : {
752 2 : return *buf = _php_pgsql_trim_message(PQerrorMessage(pgsql), NULL);
753 : }
754 : /* }}} */
755 :
756 : #define PQErrorMessageTrim(pgsql, buf) _php_pgsql_trim_result(pgsql, buf)
757 :
758 : #define PHP_PQ_ERROR(text, pgsql) { \
759 : char *msgbuf = _php_pgsql_trim_message(PQerrorMessage(pgsql), NULL); \
760 : php_error_docref(NULL TSRMLS_CC, E_WARNING, text, msgbuf); \
761 : efree(msgbuf); \
762 : } \
763 :
764 : /* {{{ php_pgsql_set_default_link
765 : */
766 : static void php_pgsql_set_default_link(int id TSRMLS_DC)
767 87 : {
768 87 : zend_list_addref(id);
769 :
770 87 : if (PGG(default_link) != -1) {
771 0 : zend_list_delete(PGG(default_link));
772 : }
773 :
774 87 : PGG(default_link) = id;
775 87 : }
776 : /* }}} */
777 :
778 : /* {{{ _close_pgsql_link
779 : */
780 : static void _close_pgsql_link(zend_rsrc_list_entry *rsrc TSRMLS_DC)
781 86 : {
782 86 : PGconn *link = (PGconn *)rsrc->ptr;
783 : PGresult *res;
784 :
785 174 : while ((res = PQgetResult(link))) {
786 2 : PQclear(res);
787 : }
788 86 : PQfinish(link);
789 86 : PGG(num_links)--;
790 86 : }
791 : /* }}} */
792 :
793 : /* {{{ _close_pgsql_plink
794 : */
795 : static void _close_pgsql_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC)
796 1 : {
797 1 : PGconn *link = (PGconn *)rsrc->ptr;
798 : PGresult *res;
799 :
800 2 : while ((res = PQgetResult(link))) {
801 0 : PQclear(res);
802 : }
803 1 : PQfinish(link);
804 1 : PGG(num_persistent)--;
805 1 : PGG(num_links)--;
806 1 : }
807 : /* }}} */
808 :
809 : /* {{{ _php_pgsql_notice_handler
810 : */
811 : static void _php_pgsql_notice_handler(void *resource_id, const char *message)
812 7 : {
813 : php_pgsql_notice *notice;
814 :
815 : TSRMLS_FETCH();
816 7 : if (! PGG(ignore_notices)) {
817 7 : notice = (php_pgsql_notice *)emalloc(sizeof(php_pgsql_notice));
818 7 : notice->message = _php_pgsql_trim_message(message, ¬ice->len);
819 7 : if (PGG(log_notices)) {
820 1 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s", notice->message);
821 : }
822 7 : zend_hash_index_update(&PGG(notices), (ulong)resource_id, (void **)¬ice, sizeof(php_pgsql_notice *), NULL);
823 : }
824 7 : }
825 : /* }}} */
826 :
827 : #define PHP_PGSQL_NOTICE_PTR_DTOR (void (*)(void *))_php_pgsql_notice_ptr_dtor
828 :
829 : /* {{{ _php_pgsql_notice_dtor
830 : */
831 : static void _php_pgsql_notice_ptr_dtor(void **ptr)
832 7 : {
833 7 : php_pgsql_notice *notice = (php_pgsql_notice *)*ptr;
834 7 : if (notice) {
835 7 : efree(notice->message);
836 7 : efree(notice);
837 7 : notice = NULL;
838 : }
839 7 : }
840 : /* }}} */
841 :
842 : /* {{{ _rollback_transactions
843 : */
844 : static int _rollback_transactions(zend_rsrc_list_entry *rsrc TSRMLS_DC)
845 328 : {
846 : PGconn *link;
847 : PGresult *res;
848 : int orig;
849 :
850 328 : if (Z_TYPE_P(rsrc) != le_plink)
851 327 : return 0;
852 :
853 1 : link = (PGconn *) rsrc->ptr;
854 :
855 1 : if (PQ_SETNONBLOCKING(link, 0)) {
856 0 : php_error_docref("ref.pgsql" TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
857 0 : return -1;
858 : }
859 :
860 2 : while ((res = PQgetResult(link))) {
861 0 : PQclear(res);
862 : }
863 : #if HAVE_PGTRANSACTIONSTATUS && HAVE_PQPROTOCOLVERSION
864 1 : if ((PQprotocolVersion(link) >= 3 && PQtransactionStatus(link) != PQTRANS_IDLE) || PQprotocolVersion(link) < 3)
865 : #endif
866 : {
867 0 : orig = PGG(ignore_notices);
868 0 : PGG(ignore_notices) = 1;
869 : #if HAVE_PGTRANSACTIONSTATUS && HAVE_PQPROTOCOLVERSION
870 0 : res = PQexec(link,"ROLLBACK;");
871 : #else
872 : res = PQexec(link,"BEGIN;");
873 : PQclear(res);
874 : res = PQexec(link,"ROLLBACK;");
875 : #endif
876 0 : PQclear(res);
877 0 : PGG(ignore_notices) = orig;
878 : }
879 :
880 1 : return 0;
881 : }
882 : /* }}} */
883 :
884 : /* {{{ _free_ptr
885 : */
886 : static void _free_ptr(zend_rsrc_list_entry *rsrc TSRMLS_DC)
887 1641 : {
888 1641 : pgLofp *lofp = (pgLofp *)rsrc->ptr;
889 1641 : efree(lofp);
890 1641 : }
891 : /* }}} */
892 :
893 : /* {{{ _free_result
894 : */
895 : static void _free_result(zend_rsrc_list_entry *rsrc TSRMLS_DC)
896 1129 : {
897 1129 : pgsql_result_handle *pg_result = (pgsql_result_handle *)rsrc->ptr;
898 :
899 1129 : PQclear(pg_result->result);
900 1129 : efree(pg_result);
901 1129 : }
902 : /* }}} */
903 :
904 : /* {{{ PHP_INI
905 : */
906 : PHP_INI_BEGIN()
907 : STD_PHP_INI_BOOLEAN( "pgsql.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_persistent, zend_pgsql_globals, pgsql_globals)
908 : STD_PHP_INI_ENTRY_EX("pgsql.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_persistent, zend_pgsql_globals, pgsql_globals, display_link_numbers)
909 : STD_PHP_INI_ENTRY_EX("pgsql.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_pgsql_globals, pgsql_globals, display_link_numbers)
910 : STD_PHP_INI_BOOLEAN( "pgsql.auto_reset_persistent", "0", PHP_INI_SYSTEM, OnUpdateBool, auto_reset_persistent, zend_pgsql_globals, pgsql_globals)
911 : STD_PHP_INI_BOOLEAN( "pgsql.ignore_notice", "0", PHP_INI_ALL, OnUpdateBool, ignore_notices, zend_pgsql_globals, pgsql_globals)
912 : STD_PHP_INI_BOOLEAN( "pgsql.log_notice", "0", PHP_INI_ALL, OnUpdateBool, log_notices, zend_pgsql_globals, pgsql_globals)
913 : PHP_INI_END()
914 : /* }}} */
915 :
916 : /* {{{ PHP_GINIT_FUNCTION
917 : */
918 : static PHP_GINIT_FUNCTION(pgsql)
919 17633 : {
920 17633 : memset(pgsql_globals, 0, sizeof(zend_pgsql_globals));
921 : /* Initilize notice message hash at MINIT only */
922 17633 : zend_hash_init_ex(&pgsql_globals->notices, 0, NULL, PHP_PGSQL_NOTICE_PTR_DTOR, 1, 0);
923 17633 : }
924 : /* }}} */
925 :
926 : /* {{{ PHP_MINIT_FUNCTION
927 : */
928 : PHP_MINIT_FUNCTION(pgsql)
929 17633 : {
930 17633 : REGISTER_INI_ENTRIES();
931 :
932 17633 : le_link = zend_register_list_destructors_ex(_close_pgsql_link, NULL, "pgsql link", module_number);
933 17633 : le_plink = zend_register_list_destructors_ex(NULL, _close_pgsql_plink, "pgsql link persistent", module_number);
934 17633 : le_result = zend_register_list_destructors_ex(_free_result, NULL, "pgsql result", module_number);
935 17633 : le_lofp = zend_register_list_destructors_ex(_free_ptr, NULL, "pgsql large object", module_number);
936 17633 : le_string = zend_register_list_destructors_ex(_free_ptr, NULL, "pgsql string", module_number);
937 : /* For connection option */
938 17633 : REGISTER_LONG_CONSTANT("PGSQL_CONNECT_FORCE_NEW", PGSQL_CONNECT_FORCE_NEW, CONST_CS | CONST_PERSISTENT);
939 : /* For pg_fetch_array() */
940 17633 : REGISTER_LONG_CONSTANT("PGSQL_ASSOC", PGSQL_ASSOC, CONST_CS | CONST_PERSISTENT);
941 17633 : REGISTER_LONG_CONSTANT("PGSQL_NUM", PGSQL_NUM, CONST_CS | CONST_PERSISTENT);
942 17633 : REGISTER_LONG_CONSTANT("PGSQL_BOTH", PGSQL_BOTH, CONST_CS | CONST_PERSISTENT);
943 : /* For pg_connection_status() */
944 17633 : REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_BAD", CONNECTION_BAD, CONST_CS | CONST_PERSISTENT);
945 17633 : REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_OK", CONNECTION_OK, CONST_CS | CONST_PERSISTENT);
946 : #if HAVE_PGTRANSACTIONSTATUS
947 : /* For pg_transaction_status() */
948 17633 : REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_IDLE", PQTRANS_IDLE, CONST_CS | CONST_PERSISTENT);
949 17633 : REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_ACTIVE", PQTRANS_ACTIVE, CONST_CS | CONST_PERSISTENT);
950 17633 : REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_INTRANS", PQTRANS_INTRANS, CONST_CS | CONST_PERSISTENT);
951 17633 : REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_INERROR", PQTRANS_INERROR, CONST_CS | CONST_PERSISTENT);
952 17633 : REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_UNKNOWN", PQTRANS_UNKNOWN, CONST_CS | CONST_PERSISTENT);
953 : #endif
954 : #if HAVE_PQSETERRORVERBOSITY
955 : /* For pg_set_error_verbosity() */
956 17633 : REGISTER_LONG_CONSTANT("PGSQL_ERRORS_TERSE", PQERRORS_TERSE, CONST_CS | CONST_PERSISTENT);
957 17633 : REGISTER_LONG_CONSTANT("PGSQL_ERRORS_DEFAULT", PQERRORS_DEFAULT, CONST_CS | CONST_PERSISTENT);
958 17633 : REGISTER_LONG_CONSTANT("PGSQL_ERRORS_VERBOSE", PQERRORS_VERBOSE, CONST_CS | CONST_PERSISTENT);
959 : #endif
960 : /* For lo_seek() */
961 17633 : REGISTER_LONG_CONSTANT("PGSQL_SEEK_SET", SEEK_SET, CONST_CS | CONST_PERSISTENT);
962 17633 : REGISTER_LONG_CONSTANT("PGSQL_SEEK_CUR", SEEK_CUR, CONST_CS | CONST_PERSISTENT);
963 17633 : REGISTER_LONG_CONSTANT("PGSQL_SEEK_END", SEEK_END, CONST_CS | CONST_PERSISTENT);
964 : /* For pg_result_status() return value type */
965 17633 : REGISTER_LONG_CONSTANT("PGSQL_STATUS_LONG", PGSQL_STATUS_LONG, CONST_CS | CONST_PERSISTENT);
966 17633 : REGISTER_LONG_CONSTANT("PGSQL_STATUS_STRING", PGSQL_STATUS_STRING, CONST_CS | CONST_PERSISTENT);
967 : /* For pg_result_status() return value */
968 17633 : REGISTER_LONG_CONSTANT("PGSQL_EMPTY_QUERY", PGRES_EMPTY_QUERY, CONST_CS | CONST_PERSISTENT);
969 17633 : REGISTER_LONG_CONSTANT("PGSQL_COMMAND_OK", PGRES_COMMAND_OK, CONST_CS | CONST_PERSISTENT);
970 17633 : REGISTER_LONG_CONSTANT("PGSQL_TUPLES_OK", PGRES_TUPLES_OK, CONST_CS | CONST_PERSISTENT);
971 17633 : REGISTER_LONG_CONSTANT("PGSQL_COPY_OUT", PGRES_COPY_OUT, CONST_CS | CONST_PERSISTENT);
972 17633 : REGISTER_LONG_CONSTANT("PGSQL_COPY_IN", PGRES_COPY_IN, CONST_CS | CONST_PERSISTENT);
973 17633 : REGISTER_LONG_CONSTANT("PGSQL_BAD_RESPONSE", PGRES_BAD_RESPONSE, CONST_CS | CONST_PERSISTENT);
974 17633 : REGISTER_LONG_CONSTANT("PGSQL_NONFATAL_ERROR", PGRES_NONFATAL_ERROR, CONST_CS | CONST_PERSISTENT);
975 17633 : REGISTER_LONG_CONSTANT("PGSQL_FATAL_ERROR", PGRES_FATAL_ERROR, CONST_CS | CONST_PERSISTENT);
976 : #if HAVE_PQRESULTERRORFIELD
977 : /* For pg_result_error_field() field codes */
978 17633 : REGISTER_LONG_CONSTANT("PGSQL_DIAG_SEVERITY", PG_DIAG_SEVERITY, CONST_CS | CONST_PERSISTENT);
979 17633 : REGISTER_LONG_CONSTANT("PGSQL_DIAG_SQLSTATE", PG_DIAG_SQLSTATE, CONST_CS | CONST_PERSISTENT);
980 17633 : REGISTER_LONG_CONSTANT("PGSQL_DIAG_MESSAGE_PRIMARY", PG_DIAG_MESSAGE_PRIMARY, CONST_CS | CONST_PERSISTENT);
981 17633 : REGISTER_LONG_CONSTANT("PGSQL_DIAG_MESSAGE_DETAIL", PG_DIAG_MESSAGE_DETAIL, CONST_CS | CONST_PERSISTENT);
982 17633 : REGISTER_LONG_CONSTANT("PGSQL_DIAG_MESSAGE_HINT", PG_DIAG_MESSAGE_HINT, CONST_CS | CONST_PERSISTENT);
983 17633 : REGISTER_LONG_CONSTANT("PGSQL_DIAG_STATEMENT_POSITION", PG_DIAG_STATEMENT_POSITION, CONST_CS | CONST_PERSISTENT);
984 : #ifdef PG_DIAG_INTERNAL_POSITION
985 17633 : REGISTER_LONG_CONSTANT("PGSQL_DIAG_INTERNAL_POSITION", PG_DIAG_INTERNAL_POSITION, CONST_CS | CONST_PERSISTENT);
986 : #endif
987 : #ifdef PG_DIAG_INTERNAL_QUERY
988 17633 : REGISTER_LONG_CONSTANT("PGSQL_DIAG_INTERNAL_QUERY", PG_DIAG_INTERNAL_QUERY, CONST_CS | CONST_PERSISTENT);
989 : #endif
990 17633 : REGISTER_LONG_CONSTANT("PGSQL_DIAG_CONTEXT", PG_DIAG_CONTEXT, CONST_CS | CONST_PERSISTENT);
991 17633 : REGISTER_LONG_CONSTANT("PGSQL_DIAG_SOURCE_FILE", PG_DIAG_SOURCE_FILE, CONST_CS | CONST_PERSISTENT);
992 17633 : REGISTER_LONG_CONSTANT("PGSQL_DIAG_SOURCE_LINE", PG_DIAG_SOURCE_LINE, CONST_CS | CONST_PERSISTENT);
993 17633 : REGISTER_LONG_CONSTANT("PGSQL_DIAG_SOURCE_FUNCTION", PG_DIAG_SOURCE_FUNCTION, CONST_CS | CONST_PERSISTENT);
994 : #endif
995 : /* pg_convert options */
996 17633 : REGISTER_LONG_CONSTANT("PGSQL_CONV_IGNORE_DEFAULT", PGSQL_CONV_IGNORE_DEFAULT, CONST_CS | CONST_PERSISTENT);
997 17633 : REGISTER_LONG_CONSTANT("PGSQL_CONV_FORCE_NULL", PGSQL_CONV_FORCE_NULL, CONST_CS | CONST_PERSISTENT);
998 17633 : REGISTER_LONG_CONSTANT("PGSQL_CONV_IGNORE_NOT_NULL", PGSQL_CONV_IGNORE_NOT_NULL, CONST_CS | CONST_PERSISTENT);
999 : /* pg_insert/update/delete/select options */
1000 17633 : REGISTER_LONG_CONSTANT("PGSQL_DML_NO_CONV", PGSQL_DML_NO_CONV, CONST_CS | CONST_PERSISTENT);
1001 17633 : REGISTER_LONG_CONSTANT("PGSQL_DML_EXEC", PGSQL_DML_EXEC, CONST_CS | CONST_PERSISTENT);
1002 17633 : REGISTER_LONG_CONSTANT("PGSQL_DML_ASYNC", PGSQL_DML_ASYNC, CONST_CS | CONST_PERSISTENT);
1003 17633 : REGISTER_LONG_CONSTANT("PGSQL_DML_STRING", PGSQL_DML_STRING, CONST_CS | CONST_PERSISTENT);
1004 17633 : return SUCCESS;
1005 : }
1006 : /* }}} */
1007 :
1008 : /* {{{ PHP_MSHUTDOWN_FUNCTION
1009 : */
1010 : PHP_MSHUTDOWN_FUNCTION(pgsql)
1011 17665 : {
1012 17665 : UNREGISTER_INI_ENTRIES();
1013 17665 : zend_hash_destroy(&PGG(notices));
1014 :
1015 17665 : return SUCCESS;
1016 : }
1017 : /* }}} */
1018 :
1019 : /* {{{ PHP_RINIT_FUNCTION
1020 : */
1021 : PHP_RINIT_FUNCTION(pgsql)
1022 17619 : {
1023 17619 : PGG(default_link)=-1;
1024 17619 : PGG(num_links) = PGG(num_persistent);
1025 17619 : return SUCCESS;
1026 : }
1027 : /* }}} */
1028 :
1029 : /* {{{ PHP_RSHUTDOWN_FUNCTION
1030 : */
1031 : PHP_RSHUTDOWN_FUNCTION(pgsql)
1032 17651 : {
1033 : /* clean up notice messages */
1034 17651 : zend_hash_clean(&PGG(notices));
1035 : /* clean up persistent connection */
1036 17651 : zend_hash_apply(&EG(persistent_list), (apply_func_t) _rollback_transactions TSRMLS_CC);
1037 17651 : return SUCCESS;
1038 : }
1039 : /* }}} */
1040 :
1041 : /* {{{ PHP_MINFO_FUNCTION
1042 : */
1043 : PHP_MINFO_FUNCTION(pgsql)
1044 42 : {
1045 : char buf[256];
1046 :
1047 42 : php_info_print_table_start();
1048 42 : php_info_print_table_header(2, "PostgreSQL Support", "enabled");
1049 : #if HAVE_PG_CONFIG_H
1050 42 : php_info_print_table_row(2, "PostgreSQL(libpq) Version", PG_VERSION);
1051 : #ifdef HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT
1052 42 : php_info_print_table_row(2, "Multibyte character support", "enabled");
1053 : #else
1054 : php_info_print_table_row(2, "Multibyte character support", "disabled");
1055 : #endif
1056 : #ifdef USE_SSL
1057 42 : php_info_print_table_row(2, "SSL support", "enabled");
1058 : #else
1059 : php_info_print_table_row(2, "SSL support", "disabled");
1060 : #endif
1061 : #endif /* HAVE_PG_CONFIG_H */
1062 42 : snprintf(buf, sizeof(buf), "%ld", PGG(num_persistent));
1063 42 : php_info_print_table_row(2, "Active Persistent Links", buf);
1064 42 : snprintf(buf, sizeof(buf), "%ld", PGG(num_links));
1065 42 : php_info_print_table_row(2, "Active Links", buf);
1066 42 : php_info_print_table_end();
1067 :
1068 42 : DISPLAY_INI_ENTRIES();
1069 42 : }
1070 : /* }}} */
1071 :
1072 :
1073 : /* {{{ php_pgsql_do_connect
1074 : */
1075 : static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
1076 87 : {
1077 87 : char *host=NULL,*port=NULL,*options=NULL,*tty=NULL,*dbname=NULL,*connstring=NULL;
1078 : PGconn *pgsql;
1079 87 : smart_str str = {0};
1080 : zval **args[5];
1081 87 : int i, connect_type = 0;
1082 : PGresult *pg_result;
1083 :
1084 87 : if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 5
1085 : || zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
1086 0 : WRONG_PARAM_COUNT;
1087 : }
1088 :
1089 87 : smart_str_appends(&str, "pgsql");
1090 :
1091 174 : for (i = 0; i < ZEND_NUM_ARGS(); i++) {
1092 : /* make sure that the PGSQL_CONNECT_FORCE_NEW bit is not part of the hash so that subsequent connections
1093 : * can re-use this connection. Bug #39979
1094 : */
1095 87 : if (i == 1 && ZEND_NUM_ARGS() == 2 && Z_TYPE_PP(args[i]) == IS_LONG) {
1096 0 : if (Z_LVAL_PP(args[1]) == PGSQL_CONNECT_FORCE_NEW) {
1097 0 : continue;
1098 0 : } else if (Z_LVAL_PP(args[1]) & PGSQL_CONNECT_FORCE_NEW) {
1099 0 : smart_str_append_long(&str, Z_LVAL_PP(args[1]) ^ PGSQL_CONNECT_FORCE_NEW);
1100 : }
1101 : }
1102 87 : convert_to_string_ex(args[i]);
1103 87 : smart_str_appendc(&str, '_');
1104 87 : smart_str_appendl(&str, Z_STRVAL_PP(args[i]), Z_STRLEN_PP(args[i]));
1105 : }
1106 :
1107 87 : smart_str_0(&str);
1108 :
1109 87 : if (ZEND_NUM_ARGS() == 1) { /* new style, using connection string */
1110 87 : connstring = Z_STRVAL_PP(args[0]);
1111 0 : } else if (ZEND_NUM_ARGS() == 2 ) { /* Safe to add conntype_option, since 2 args was illegal */
1112 0 : connstring = Z_STRVAL_PP(args[0]);
1113 0 : convert_to_long_ex(args[1]);
1114 0 : connect_type = Z_LVAL_PP(args[1]);
1115 : } else {
1116 0 : host = Z_STRVAL_PP(args[0]);
1117 0 : port = Z_STRVAL_PP(args[1]);
1118 0 : dbname = Z_STRVAL_PP(args[ZEND_NUM_ARGS()-1]);
1119 :
1120 0 : switch (ZEND_NUM_ARGS()) {
1121 : case 5:
1122 0 : tty = Z_STRVAL_PP(args[3]);
1123 : /* fall through */
1124 : case 4:
1125 0 : options = Z_STRVAL_PP(args[2]);
1126 : break;
1127 : }
1128 : }
1129 :
1130 88 : if (persistent && PGG(allow_persistent)) {
1131 : zend_rsrc_list_entry *le;
1132 :
1133 : /* try to find if we already have this link in our persistent list */
1134 1 : if (zend_hash_find(&EG(persistent_list), str.c, str.len+1, (void **) &le)==FAILURE) { /* we don't */
1135 : zend_rsrc_list_entry new_le;
1136 :
1137 1 : if (PGG(max_links)!=-1 && PGG(num_links)>=PGG(max_links)) {
1138 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING,
1139 : "Cannot create new link. Too many open links (%ld)", PGG(num_links));
1140 0 : goto err;
1141 : }
1142 1 : if (PGG(max_persistent)!=-1 && PGG(num_persistent)>=PGG(max_persistent)) {
1143 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING,
1144 : "Cannot create new link. Too many open persistent links (%ld)", PGG(num_persistent));
1145 0 : goto err;
1146 : }
1147 :
1148 : /* create the link */
1149 1 : if (connstring) {
1150 1 : pgsql=PQconnectdb(connstring);
1151 : } else {
1152 0 : pgsql=PQsetdb(host,port,options,tty,dbname);
1153 : }
1154 1 : if (pgsql==NULL || PQstatus(pgsql)==CONNECTION_BAD) {
1155 0 : PHP_PQ_ERROR("Unable to connect to PostgreSQL server: %s", pgsql)
1156 0 : if (pgsql) {
1157 0 : PQfinish(pgsql);
1158 : }
1159 0 : goto err;
1160 : }
1161 :
1162 : /* hash it up */
1163 1 : Z_TYPE(new_le) = le_plink;
1164 1 : new_le.ptr = pgsql;
1165 1 : if (zend_hash_update(&EG(persistent_list), str.c, str.len+1, (void *) &new_le, sizeof(zend_rsrc_list_entry), NULL)==FAILURE) {
1166 0 : goto err;
1167 : }
1168 1 : PGG(num_links)++;
1169 1 : PGG(num_persistent)++;
1170 : } else { /* we do */
1171 0 : if (Z_TYPE_P(le) != le_plink) {
1172 0 : RETURN_FALSE;
1173 : }
1174 : /* ensure that the link did not die */
1175 0 : if (PGG(auto_reset_persistent) & 1) {
1176 : /* need to send & get something from backend to
1177 : make sure we catch CONNECTION_BAD everytime */
1178 : PGresult *pg_result;
1179 0 : pg_result = PQexec(le->ptr, "select 1");
1180 0 : PQclear(pg_result);
1181 : }
1182 0 : if (PQstatus(le->ptr)==CONNECTION_BAD) { /* the link died */
1183 0 : if (le->ptr == NULL) {
1184 0 : if (connstring) {
1185 0 : le->ptr=PQconnectdb(connstring);
1186 : } else {
1187 0 : le->ptr=PQsetdb(host,port,options,tty,dbname);
1188 : }
1189 : }
1190 : else {
1191 0 : PQreset(le->ptr);
1192 : }
1193 0 : if (le->ptr==NULL || PQstatus(le->ptr)==CONNECTION_BAD) {
1194 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING,"PostgreSQL link lost, unable to reconnect");
1195 0 : zend_hash_del(&EG(persistent_list),str.c,str.len+1);
1196 0 : goto err;
1197 : }
1198 : }
1199 0 : pgsql = (PGconn *) le->ptr;
1200 : #if HAVE_PQPROTOCOLVERSION && HAVE_PQPARAMETERSTATUS
1201 0 : if (PQprotocolVersion(pgsql) >= 3 && atof(PQparameterStatus(pgsql, "server_version")) >= 7.2) {
1202 : #else
1203 : if (atof(PG_VERSION) >= 7.2) {
1204 : #endif
1205 0 : pg_result = PQexec(pgsql, "RESET ALL;");
1206 0 : PQclear(pg_result);
1207 : }
1208 : }
1209 1 : ZEND_REGISTER_RESOURCE(return_value, pgsql, le_plink);
1210 : } else { /* Non persistent connection */
1211 : zend_rsrc_list_entry *index_ptr,new_index_ptr;
1212 :
1213 : /* first we check the hash for the hashed_details key. if it exists,
1214 : * it should point us to the right offset where the actual pgsql link sits.
1215 : * if it doesn't, open a new pgsql link, add it to the resource list,
1216 : * and add a pointer to it with hashed_details as the key.
1217 : */
1218 86 : if (!(connect_type & PGSQL_CONNECT_FORCE_NEW)
1219 : && zend_hash_find(&EG(regular_list),str.c,str.len+1,(void **) &index_ptr)==SUCCESS) {
1220 : int type;
1221 : ulong link;
1222 : void *ptr;
1223 :
1224 1 : if (Z_TYPE_P(index_ptr) != le_index_ptr) {
1225 0 : RETURN_FALSE;
1226 : }
1227 1 : link = (uintptr_t) index_ptr->ptr;
1228 1 : ptr = zend_list_find(link,&type); /* check if the link is still there */
1229 1 : if (ptr && (type==le_link || type==le_plink)) {
1230 0 : Z_LVAL_P(return_value) = link;
1231 0 : zend_list_addref(link);
1232 0 : php_pgsql_set_default_link(link TSRMLS_CC);
1233 0 : Z_TYPE_P(return_value) = IS_RESOURCE;
1234 0 : goto cleanup;
1235 : } else {
1236 1 : zend_hash_del(&EG(regular_list),str.c,str.len+1);
1237 : }
1238 : }
1239 86 : if (PGG(max_links)!=-1 && PGG(num_links)>=PGG(max_links)) {
1240 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create new link. Too many open links (%ld)", PGG(num_links));
1241 0 : goto err;
1242 : }
1243 86 : if (connstring) {
1244 86 : pgsql = PQconnectdb(connstring);
1245 : } else {
1246 0 : pgsql = PQsetdb(host,port,options,tty,dbname);
1247 : }
1248 86 : if (pgsql==NULL || PQstatus(pgsql)==CONNECTION_BAD) {
1249 0 : PHP_PQ_ERROR("Unable to connect to PostgreSQL server: %s", pgsql);
1250 0 : if (pgsql) {
1251 0 : PQfinish(pgsql);
1252 : }
1253 0 : goto err;
1254 : }
1255 :
1256 : /* add it to the list */
1257 86 : ZEND_REGISTER_RESOURCE(return_value, pgsql, le_link);
1258 :
1259 : /* add it to the hash */
1260 86 : new_index_ptr.ptr = (void *) Z_LVAL_P(return_value);
1261 86 : Z_TYPE(new_index_ptr) = le_index_ptr;
1262 86 : if (zend_hash_update(&EG(regular_list),str.c,str.len+1,(void *) &new_index_ptr, sizeof(zend_rsrc_list_entry), NULL)==FAILURE) {
1263 0 : goto err;
1264 : }
1265 86 : PGG(num_links)++;
1266 : }
1267 : /* set notice processer */
1268 87 : if (! PGG(ignore_notices) && Z_TYPE_P(return_value) == IS_RESOURCE) {
1269 87 : PQsetNoticeProcessor(pgsql, _php_pgsql_notice_handler, (void*)Z_RESVAL_P(return_value));
1270 : }
1271 87 : php_pgsql_set_default_link(Z_LVAL_P(return_value) TSRMLS_CC);
1272 :
1273 87 : cleanup:
1274 87 : smart_str_free(&str);
1275 87 : return;
1276 :
1277 0 : err:
1278 0 : smart_str_free(&str);
1279 0 : RETURN_FALSE;
1280 : }
1281 : /* }}} */
1282 :
1283 : #if 0
1284 : /* {{{ php_pgsql_get_default_link
1285 : */
1286 : static int php_pgsql_get_default_link(INTERNAL_FUNCTION_PARAMETERS)
1287 : {
1288 : if (PGG(default_link)==-1) { /* no link opened yet, implicitly open one */
1289 : ht = 0;
1290 : php_pgsql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
1291 : }
1292 : return PGG(default_link);
1293 : }
1294 : /* }}} */
1295 : #endif
1296 :
1297 : /* {{{ proto resource pg_connect(string connection_string[, int connect_type] | [string host, string port [, string options [, string tty,]]] string database)
1298 : Open a PostgreSQL connection */
1299 : PHP_FUNCTION(pg_connect)
1300 86 : {
1301 86 : php_pgsql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
1302 86 : }
1303 : /* }}} */
1304 :
1305 : /* {{{ proto resource pg_pconnect(string connection_string | [string host, string port [, string options [, string tty,]]] string database)
1306 : Open a persistent PostgreSQL connection */
1307 : PHP_FUNCTION(pg_pconnect)
1308 1 : {
1309 1 : php_pgsql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,1);
1310 1 : }
1311 : /* }}} */
1312 :
1313 : /* {{{ proto bool pg_close([resource connection])
1314 : Close a PostgreSQL connection */
1315 : PHP_FUNCTION(pg_close)
1316 17 : {
1317 17 : zval *pgsql_link = NULL;
1318 17 : int id = -1, argc = ZEND_NUM_ARGS();
1319 : PGconn *pgsql;
1320 :
1321 17 : if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) {
1322 0 : return;
1323 : }
1324 :
1325 17 : if (argc == 0) {
1326 0 : id = PGG(default_link);
1327 0 : CHECK_DEFAULT_LINK(id);
1328 : }
1329 :
1330 17 : if (pgsql_link == NULL && id == -1) {
1331 0 : RETURN_FALSE;
1332 : }
1333 :
1334 17 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
1335 :
1336 17 : if (id==-1) { /* explicit resource number */
1337 17 : zend_list_delete(Z_RESVAL_P(pgsql_link));
1338 : }
1339 :
1340 17 : if (id!=-1
1341 : || (pgsql_link && Z_RESVAL_P(pgsql_link)==PGG(default_link))) {
1342 17 : zend_list_delete(PGG(default_link));
1343 17 : PGG(default_link) = -1;
1344 : }
1345 :
1346 17 : RETURN_TRUE;
1347 : }
1348 : /* }}} */
1349 :
1350 :
1351 : #define PHP_PG_DBNAME 1
1352 : #define PHP_PG_ERROR_MESSAGE 2
1353 : #define PHP_PG_OPTIONS 3
1354 : #define PHP_PG_PORT 4
1355 : #define PHP_PG_TTY 5
1356 : #define PHP_PG_HOST 6
1357 : #define PHP_PG_VERSION 7
1358 :
1359 : /* {{{ php_pgsql_get_link_info
1360 : */
1361 : static void php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
1362 13 : {
1363 13 : zval *pgsql_link = NULL;
1364 13 : int id = -1, argc = ZEND_NUM_ARGS();
1365 : PGconn *pgsql;
1366 : char *msgbuf;
1367 :
1368 13 : if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) {
1369 0 : return;
1370 : }
1371 :
1372 13 : if (argc == 0) {
1373 2 : id = PGG(default_link);
1374 2 : CHECK_DEFAULT_LINK(id);
1375 : }
1376 :
1377 13 : if (pgsql_link == NULL && id == -1) {
1378 0 : RETURN_FALSE;
1379 : }
1380 :
1381 13 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
1382 :
1383 13 : switch(entry_type) {
1384 : case PHP_PG_DBNAME:
1385 1 : Z_STRVAL_P(return_value) = PQdb(pgsql);
1386 1 : break;
1387 : case PHP_PG_ERROR_MESSAGE:
1388 2 : RETURN_STRING(PQErrorMessageTrim(pgsql, &msgbuf), 0);
1389 : return;
1390 : case PHP_PG_OPTIONS:
1391 1 : Z_STRVAL_P(return_value) = PQoptions(pgsql);
1392 1 : break;
1393 : case PHP_PG_PORT:
1394 1 : Z_STRVAL_P(return_value) = PQport(pgsql);
1395 1 : break;
1396 : case PHP_PG_TTY:
1397 1 : Z_STRVAL_P(return_value) = PQtty(pgsql);
1398 1 : break;
1399 : case PHP_PG_HOST:
1400 1 : Z_STRVAL_P(return_value) = PQhost(pgsql);
1401 1 : break;
1402 : case PHP_PG_VERSION:
1403 6 : array_init(return_value);
1404 6 : add_assoc_string(return_value, "client", PG_VERSION, 1);
1405 : #if HAVE_PQPROTOCOLVERSION
1406 6 : add_assoc_long(return_value, "protocol", PQprotocolVersion(pgsql));
1407 : #if HAVE_PQPARAMETERSTATUS
1408 6 : if (PQprotocolVersion(pgsql) >= 3) {
1409 6 : add_assoc_string(return_value, "server", (char*)PQparameterStatus(pgsql, "server_version"), 1);
1410 : }
1411 : #endif
1412 : #endif
1413 6 : return;
1414 : default:
1415 0 : RETURN_FALSE;
1416 : }
1417 5 : if (Z_STRVAL_P(return_value)) {
1418 5 : Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
1419 5 : Z_STRVAL_P(return_value) = (char *) estrdup(Z_STRVAL_P(return_value));
1420 : } else {
1421 0 : Z_STRLEN_P(return_value) = 0;
1422 0 : Z_STRVAL_P(return_value) = (char *) estrdup("");
1423 : }
1424 5 : Z_TYPE_P(return_value) = IS_STRING;
1425 : }
1426 : /* }}} */
1427 :
1428 : /* {{{ proto string pg_dbname([resource connection])
1429 : Get the database name */
1430 : PHP_FUNCTION(pg_dbname)
1431 1 : {
1432 1 : php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_DBNAME);
1433 1 : }
1434 : /* }}} */
1435 :
1436 : /* {{{ proto string pg_last_error([resource connection])
1437 : Get the error message string */
1438 : PHP_FUNCTION(pg_last_error)
1439 2 : {
1440 2 : php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_ERROR_MESSAGE);
1441 2 : }
1442 : /* }}} */
1443 :
1444 : /* {{{ proto string pg_options([resource connection])
1445 : Get the options associated with the connection */
1446 : PHP_FUNCTION(pg_options)
1447 1 : {
1448 1 : php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_OPTIONS);
1449 1 : }
1450 : /* }}} */
1451 :
1452 : /* {{{ proto int pg_port([resource connection])
1453 : Return the port number associated with the connection */
1454 : PHP_FUNCTION(pg_port)
1455 1 : {
1456 1 : php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_PORT);
1457 1 : }
1458 : /* }}} */
1459 :
1460 : /* {{{ proto string pg_tty([resource connection])
1461 : Return the tty name associated with the connection */
1462 : PHP_FUNCTION(pg_tty)
1463 1 : {
1464 1 : php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_TTY);
1465 1 : }
1466 : /* }}} */
1467 :
1468 : /* {{{ proto string pg_host([resource connection])
1469 : Returns the host name associated with the connection */
1470 : PHP_FUNCTION(pg_host)
1471 1 : {
1472 1 : php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_HOST);
1473 1 : }
1474 : /* }}} */
1475 :
1476 : /* {{{ proto array pg_version([resource connection])
1477 : Returns an array with client, protocol and server version (when available) */
1478 : PHP_FUNCTION(pg_version)
1479 6 : {
1480 6 : php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_VERSION);
1481 6 : }
1482 : /* }}} */
1483 :
1484 : #if HAVE_PQPARAMETERSTATUS
1485 : /* {{{ proto string|false pg_parameter_status([resource connection,] string param_name)
1486 : Returns the value of a server parameter */
1487 : PHP_FUNCTION(pg_parameter_status)
1488 0 : {
1489 : zval *pgsql_link;
1490 : int id;
1491 : PGconn *pgsql;
1492 : char *param;
1493 : int len;
1494 :
1495 0 : if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pgsql_link, ¶m, &len) == SUCCESS) {
1496 0 : id = -1;
1497 0 : } else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", ¶m, &len) == SUCCESS) {
1498 0 : pgsql_link = NULL;
1499 0 : id = PGG(default_link);
1500 : } else {
1501 0 : RETURN_FALSE;
1502 : }
1503 0 : if (pgsql_link == NULL && id == -1) {
1504 0 : RETURN_FALSE;
1505 : }
1506 :
1507 0 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
1508 :
1509 0 : param = (char*)PQparameterStatus(pgsql, param);
1510 0 : if (param) {
1511 0 : RETURN_STRING(param, 1);
1512 : } else {
1513 0 : RETURN_FALSE;
1514 : }
1515 : }
1516 : /* }}} */
1517 : #endif
1518 :
1519 : /* {{{ proto bool pg_ping([resource connection])
1520 : Ping database. If connection is bad, try to reconnect. */
1521 : PHP_FUNCTION(pg_ping)
1522 1 : {
1523 : zval *pgsql_link;
1524 : int id;
1525 : PGconn *pgsql;
1526 : PGresult *res;
1527 :
1528 1 : if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r", &pgsql_link) == SUCCESS) {
1529 1 : id = -1;
1530 : } else {
1531 0 : pgsql_link = NULL;
1532 0 : id = PGG(default_link);
1533 : }
1534 1 : if (pgsql_link == NULL && id == -1) {
1535 0 : RETURN_FALSE;
1536 : }
1537 :
1538 1 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
1539 :
1540 : /* ping connection */
1541 1 : res = PQexec(pgsql, "SELECT 1;");
1542 1 : PQclear(res);
1543 :
1544 : /* check status. */
1545 1 : if (PQstatus(pgsql) == CONNECTION_OK)
1546 1 : RETURN_TRUE;
1547 :
1548 : /* reset connection if it's broken */
1549 0 : PQreset(pgsql);
1550 0 : if (PQstatus(pgsql) == CONNECTION_OK) {
1551 0 : RETURN_TRUE;
1552 : }
1553 0 : RETURN_FALSE;
1554 : }
1555 : /* }}} */
1556 :
1557 : /* {{{ proto resource pg_query([resource connection,] string query)
1558 : Execute a query */
1559 : PHP_FUNCTION(pg_query)
1560 1114 : {
1561 1114 : zval *pgsql_link = NULL;
1562 : char *query;
1563 1114 : int id = -1, query_len, argc = ZEND_NUM_ARGS();
1564 1114 : int leftover = 0;
1565 : PGconn *pgsql;
1566 : PGresult *pgsql_result;
1567 : ExecStatusType status;
1568 : pgsql_result_handle *pg_result;
1569 :
1570 1114 : if (argc == 1) {
1571 62 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &query, &query_len) == FAILURE) {
1572 0 : return;
1573 : }
1574 62 : id = PGG(default_link);
1575 62 : CHECK_DEFAULT_LINK(id);
1576 : } else {
1577 1052 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pgsql_link, &query, &query_len) == FAILURE) {
1578 0 : return;
1579 : }
1580 : }
1581 :
1582 1114 : if (pgsql_link == NULL && id == -1) {
1583 0 : RETURN_FALSE;
1584 : }
1585 :
1586 1114 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
1587 :
1588 1114 : if (PQ_SETNONBLOCKING(pgsql, 0)) {
1589 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to blocking mode");
1590 0 : RETURN_FALSE;
1591 : }
1592 2228 : while ((pgsql_result = PQgetResult(pgsql))) {
1593 0 : PQclear(pgsql_result);
1594 0 : leftover = 1;
1595 : }
1596 1114 : if (leftover) {
1597 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first");
1598 : }
1599 1114 : pgsql_result = PQexec(pgsql, query);
1600 1114 : if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
1601 0 : PQclear(pgsql_result);
1602 0 : PQreset(pgsql);
1603 0 : pgsql_result = PQexec(pgsql, query);
1604 : }
1605 :
1606 1114 : if (pgsql_result) {
1607 1114 : status = PQresultStatus(pgsql_result);
1608 : } else {
1609 0 : status = (ExecStatusType) PQstatus(pgsql);
1610 : }
1611 :
1612 1114 : switch (status) {
1613 : case PGRES_EMPTY_QUERY:
1614 : case PGRES_BAD_RESPONSE:
1615 : case PGRES_NONFATAL_ERROR:
1616 : case PGRES_FATAL_ERROR:
1617 5 : PHP_PQ_ERROR("Query failed: %s", pgsql);
1618 5 : PQclear(pgsql_result);
1619 5 : RETURN_FALSE;
1620 : break;
1621 : case PGRES_COMMAND_OK: /* successful command that did not return rows */
1622 : default:
1623 1109 : if (pgsql_result) {
1624 1109 : pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle));
1625 1109 : pg_result->conn = pgsql;
1626 1109 : pg_result->result = pgsql_result;
1627 1109 : pg_result->row = 0;
1628 1109 : ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result);
1629 : } else {
1630 0 : PQclear(pgsql_result);
1631 0 : RETURN_FALSE;
1632 : }
1633 : break;
1634 : }
1635 : }
1636 : /* }}} */
1637 :
1638 : #if HAVE_PQEXECPARAMS || HAVE_PQEXECPREPARED || HAVE_PQSENDQUERYPARAMS || HAVE_PQSENDQUERYPREPARED
1639 : /* {{{ _php_pgsql_free_params */
1640 : static void _php_pgsql_free_params(char **params, int num_params)
1641 16 : {
1642 16 : if (num_params > 0) {
1643 : int i;
1644 36 : for (i = 0; i < num_params; i++) {
1645 20 : if (params[i]) {
1646 20 : efree(params[i]);
1647 : }
1648 : }
1649 16 : efree(params);
1650 : }
1651 16 : }
1652 : /* }}} */
1653 : #endif
1654 :
1655 : #if HAVE_PQEXECPARAMS
1656 : /* {{{ proto resource pg_query_params([resource connection,] string query, array params)
1657 : Execute a query */
1658 : PHP_FUNCTION(pg_query_params)
1659 8 : {
1660 8 : zval *pgsql_link = NULL;
1661 : zval *pv_param_arr, **tmp;
1662 : char *query;
1663 8 : int query_len, id = -1, argc = ZEND_NUM_ARGS();
1664 8 : int leftover = 0;
1665 8 : int num_params = 0;
1666 8 : char **params = NULL;
1667 : PGconn *pgsql;
1668 : PGresult *pgsql_result;
1669 : ExecStatusType status;
1670 : pgsql_result_handle *pg_result;
1671 :
1672 8 : if (argc == 2) {
1673 0 : if (zend_parse_parameters(argc TSRMLS_CC, "sa", &query, &query_len, &pv_param_arr) == FAILURE) {
1674 0 : return;
1675 : }
1676 0 : id = PGG(default_link);
1677 0 : CHECK_DEFAULT_LINK(id);
1678 : } else {
1679 8 : if (zend_parse_parameters(argc TSRMLS_CC, "rsa", &pgsql_link, &query, &query_len, &pv_param_arr) == FAILURE) {
1680 0 : return;
1681 : }
1682 : }
1683 :
1684 8 : if (pgsql_link == NULL && id == -1) {
1685 0 : RETURN_FALSE;
1686 : }
1687 :
1688 8 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
1689 :
1690 8 : if (PQ_SETNONBLOCKING(pgsql, 0)) {
1691 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to blocking mode");
1692 0 : RETURN_FALSE;
1693 : }
1694 16 : while ((pgsql_result = PQgetResult(pgsql))) {
1695 0 : PQclear(pgsql_result);
1696 0 : leftover = 1;
1697 : }
1698 8 : if (leftover) {
1699 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first");
1700 : }
1701 :
1702 8 : zend_hash_internal_pointer_reset(Z_ARRVAL_P(pv_param_arr));
1703 8 : num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr));
1704 8 : if (num_params > 0) {
1705 8 : int i = 0;
1706 8 : params = (char **)safe_emalloc(sizeof(char *), num_params, 0);
1707 :
1708 17 : for(i = 0; i < num_params; i++) {
1709 9 : if (zend_hash_get_current_data(Z_ARRVAL_P(pv_param_arr), (void **) &tmp) == FAILURE) {
1710 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error getting parameter");
1711 0 : _php_pgsql_free_params(params, num_params);
1712 0 : RETURN_FALSE;
1713 : }
1714 :
1715 9 : if (Z_TYPE_PP(tmp) == IS_NULL) {
1716 0 : params[i] = NULL;
1717 : } else {
1718 9 : zval tmp_val = **tmp;
1719 9 : zval_copy_ctor(&tmp_val);
1720 9 : convert_to_string(&tmp_val);
1721 9 : if (Z_TYPE(tmp_val) != IS_STRING) {
1722 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error converting parameter");
1723 0 : zval_dtor(&tmp_val);
1724 0 : _php_pgsql_free_params(params, num_params);
1725 0 : RETURN_FALSE;
1726 : }
1727 9 : params[i] = estrndup(Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
1728 9 : zval_dtor(&tmp_val);
1729 : }
1730 :
1731 9 : zend_hash_move_forward(Z_ARRVAL_P(pv_param_arr));
1732 : }
1733 : }
1734 :
1735 8 : pgsql_result = PQexecParams(pgsql, query, num_params,
1736 : NULL, (const char * const *)params, NULL, NULL, 0);
1737 8 : if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
1738 0 : PQclear(pgsql_result);
1739 0 : PQreset(pgsql);
1740 0 : pgsql_result = PQexecParams(pgsql, query, num_params,
1741 : NULL, (const char * const *)params, NULL, NULL, 0);
1742 : }
1743 :
1744 8 : if (pgsql_result) {
1745 8 : status = PQresultStatus(pgsql_result);
1746 : } else {
1747 0 : status = (ExecStatusType) PQstatus(pgsql);
1748 : }
1749 :
1750 8 : _php_pgsql_free_params(params, num_params);
1751 :
1752 8 : switch (status) {
1753 : case PGRES_EMPTY_QUERY:
1754 : case PGRES_BAD_RESPONSE:
1755 : case PGRES_NONFATAL_ERROR:
1756 : case PGRES_FATAL_ERROR:
1757 0 : PHP_PQ_ERROR("Query failed: %s", pgsql);
1758 0 : PQclear(pgsql_result);
1759 0 : RETURN_FALSE;
1760 : break;
1761 : case PGRES_COMMAND_OK: /* successful command that did not return rows */
1762 : default:
1763 8 : if (pgsql_result) {
1764 8 : pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle));
1765 8 : pg_result->conn = pgsql;
1766 8 : pg_result->result = pgsql_result;
1767 8 : pg_result->row = 0;
1768 8 : ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result);
1769 : } else {
1770 0 : PQclear(pgsql_result);
1771 0 : RETURN_FALSE;
1772 : }
1773 : break;
1774 : }
1775 : }
1776 : /* }}} */
1777 : #endif
1778 :
1779 : #if HAVE_PQPREPARE
1780 : /* {{{ proto resource pg_prepare([resource connection,] string stmtname, string query)
1781 : Prepare a query for future execution */
1782 : PHP_FUNCTION(pg_prepare)
1783 2 : {
1784 2 : zval *pgsql_link = NULL;
1785 : char *query, *stmtname;
1786 2 : int query_len, stmtname_len, id = -1, argc = ZEND_NUM_ARGS();
1787 2 : int leftover = 0;
1788 : PGconn *pgsql;
1789 : PGresult *pgsql_result;
1790 : ExecStatusType status;
1791 : pgsql_result_handle *pg_result;
1792 :
1793 2 : if (argc == 2) {
1794 0 : if (zend_parse_parameters(argc TSRMLS_CC, "ss", &stmtname, &stmtname_len, &query, &query_len) == FAILURE) {
1795 0 : return;
1796 : }
1797 0 : id = PGG(default_link);
1798 0 : CHECK_DEFAULT_LINK(id);
1799 : } else {
1800 2 : if (zend_parse_parameters(argc TSRMLS_CC, "rss", &pgsql_link, &stmtname, &stmtname_len, &query, &query_len) == FAILURE) {
1801 0 : return;
1802 : }
1803 : }
1804 :
1805 2 : if (pgsql_link == NULL && id == -1) {
1806 0 : RETURN_FALSE;
1807 : }
1808 :
1809 2 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
1810 :
1811 2 : if (PQ_SETNONBLOCKING(pgsql, 0)) {
1812 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to blocking mode");
1813 0 : RETURN_FALSE;
1814 : }
1815 4 : while ((pgsql_result = PQgetResult(pgsql))) {
1816 0 : PQclear(pgsql_result);
1817 0 : leftover = 1;
1818 : }
1819 2 : if (leftover) {
1820 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first");
1821 : }
1822 2 : pgsql_result = PQprepare(pgsql, stmtname, query, 0, NULL);
1823 2 : if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
1824 0 : PQclear(pgsql_result);
1825 0 : PQreset(pgsql);
1826 0 : pgsql_result = PQprepare(pgsql, stmtname, query, 0, NULL);
1827 : }
1828 :
1829 2 : if (pgsql_result) {
1830 2 : status = PQresultStatus(pgsql_result);
1831 : } else {
1832 0 : status = (ExecStatusType) PQstatus(pgsql);
1833 : }
1834 :
1835 2 : switch (status) {
1836 : case PGRES_EMPTY_QUERY:
1837 : case PGRES_BAD_RESPONSE:
1838 : case PGRES_NONFATAL_ERROR:
1839 : case PGRES_FATAL_ERROR:
1840 0 : PHP_PQ_ERROR("Query failed: %s", pgsql);
1841 0 : PQclear(pgsql_result);
1842 0 : RETURN_FALSE;
1843 : break;
1844 : case PGRES_COMMAND_OK: /* successful command that did not return rows */
1845 : default:
1846 2 : if (pgsql_result) {
1847 2 : pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle));
1848 2 : pg_result->conn = pgsql;
1849 2 : pg_result->result = pgsql_result;
1850 2 : pg_result->row = 0;
1851 2 : ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result);
1852 : } else {
1853 0 : PQclear(pgsql_result);
1854 0 : RETURN_FALSE;
1855 : }
1856 : break;
1857 : }
1858 : }
1859 : /* }}} */
1860 : #endif
1861 :
1862 : #if HAVE_PQEXECPREPARED
1863 : /* {{{ proto resource pg_execute([resource connection,] string stmtname, array params)
1864 : Execute a prepared query */
1865 : PHP_FUNCTION(pg_execute)
1866 4 : {
1867 4 : zval *pgsql_link = NULL;
1868 : zval *pv_param_arr, **tmp;
1869 : char *stmtname;
1870 4 : int stmtname_len, id = -1, argc = ZEND_NUM_ARGS();
1871 4 : int leftover = 0;
1872 4 : int num_params = 0;
1873 4 : char **params = NULL;
1874 : PGconn *pgsql;
1875 : PGresult *pgsql_result;
1876 : ExecStatusType status;
1877 : pgsql_result_handle *pg_result;
1878 :
1879 4 : if (argc == 2) {
1880 0 : if (zend_parse_parameters(argc TSRMLS_CC, "sa/", &stmtname, &stmtname_len, &pv_param_arr)==FAILURE) {
1881 0 : return;
1882 : }
1883 0 : id = PGG(default_link);
1884 0 : CHECK_DEFAULT_LINK(id);
1885 : } else {
1886 4 : if (zend_parse_parameters(argc TSRMLS_CC, "rsa/", &pgsql_link, &stmtname, &stmtname_len, &pv_param_arr) == FAILURE) {
1887 0 : return;
1888 : }
1889 : }
1890 :
1891 4 : if (pgsql_link == NULL && id == -1) {
1892 0 : RETURN_FALSE;
1893 : }
1894 :
1895 4 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
1896 :
1897 4 : if (PQ_SETNONBLOCKING(pgsql, 0)) {
1898 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to blocking mode");
1899 0 : RETURN_FALSE;
1900 : }
1901 8 : while ((pgsql_result = PQgetResult(pgsql))) {
1902 0 : PQclear(pgsql_result);
1903 0 : leftover = 1;
1904 : }
1905 4 : if (leftover) {
1906 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first");
1907 : }
1908 :
1909 4 : zend_hash_internal_pointer_reset(Z_ARRVAL_P(pv_param_arr));
1910 4 : num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr));
1911 4 : if (num_params > 0) {
1912 4 : int i = 0;
1913 4 : params = (char **)safe_emalloc(sizeof(char *), num_params, 0);
1914 :
1915 9 : for(i = 0; i < num_params; i++) {
1916 5 : if (zend_hash_get_current_data(Z_ARRVAL_P(pv_param_arr), (void **) &tmp) == FAILURE) {
1917 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error getting parameter");
1918 0 : _php_pgsql_free_params(params, num_params);
1919 0 : RETURN_FALSE;
1920 : }
1921 :
1922 5 : if (Z_TYPE_PP(tmp) == IS_NULL) {
1923 0 : params[i] = NULL;
1924 : } else {
1925 5 : zval tmp_val = **tmp;
1926 5 : zval_copy_ctor(&tmp_val);
1927 5 : convert_to_string(&tmp_val);
1928 5 : if (Z_TYPE(tmp_val) != IS_STRING) {
1929 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error converting parameter");
1930 0 : zval_dtor(&tmp_val);
1931 0 : _php_pgsql_free_params(params, num_params);
1932 0 : RETURN_FALSE;
1933 : }
1934 5 : params[i] = estrndup(Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
1935 5 : zval_dtor(&tmp_val);
1936 : }
1937 :
1938 5 : zend_hash_move_forward(Z_ARRVAL_P(pv_param_arr));
1939 : }
1940 : }
1941 :
1942 4 : pgsql_result = PQexecPrepared(pgsql, stmtname, num_params,
1943 : (const char * const *)params, NULL, NULL, 0);
1944 4 : if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
1945 0 : PQclear(pgsql_result);
1946 0 : PQreset(pgsql);
1947 0 : pgsql_result = PQexecPrepared(pgsql, stmtname, num_params,
1948 : (const char * const *)params, NULL, NULL, 0);
1949 : }
1950 :
1951 4 : if (pgsql_result) {
1952 4 : status = PQresultStatus(pgsql_result);
1953 : } else {
1954 0 : status = (ExecStatusType) PQstatus(pgsql);
1955 : }
1956 :
1957 4 : _php_pgsql_free_params(params, num_params);
1958 :
1959 4 : switch (status) {
1960 : case PGRES_EMPTY_QUERY:
1961 : case PGRES_BAD_RESPONSE:
1962 : case PGRES_NONFATAL_ERROR:
1963 : case PGRES_FATAL_ERROR:
1964 0 : PHP_PQ_ERROR("Query failed: %s", pgsql);
1965 0 : PQclear(pgsql_result);
1966 0 : RETURN_FALSE;
1967 : break;
1968 : case PGRES_COMMAND_OK: /* successful command that did not return rows */
1969 : default:
1970 4 : if (pgsql_result) {
1971 4 : pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle));
1972 4 : pg_result->conn = pgsql;
1973 4 : pg_result->result = pgsql_result;
1974 4 : pg_result->row = 0;
1975 4 : ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result);
1976 : } else {
1977 0 : PQclear(pgsql_result);
1978 0 : RETURN_FALSE;
1979 : }
1980 : break;
1981 : }
1982 : }
1983 : /* }}} */
1984 : #endif
1985 :
1986 : #define PHP_PG_NUM_ROWS 1
1987 : #define PHP_PG_NUM_FIELDS 2
1988 : #define PHP_PG_CMD_TUPLES 3
1989 :
1990 : /* {{{ php_pgsql_get_result_info
1991 : */
1992 : static void php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
1993 24 : {
1994 : zval *result;
1995 : PGresult *pgsql_result;
1996 : pgsql_result_handle *pg_result;
1997 :
1998 24 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) == FAILURE) {
1999 1 : return;
2000 : }
2001 :
2002 23 : ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2003 :
2004 23 : pgsql_result = pg_result->result;
2005 :
2006 23 : switch (entry_type) {
2007 : case PHP_PG_NUM_ROWS:
2008 15 : Z_LVAL_P(return_value) = PQntuples(pgsql_result);
2009 15 : break;
2010 : case PHP_PG_NUM_FIELDS:
2011 7 : Z_LVAL_P(return_value) = PQnfields(pgsql_result);
2012 7 : break;
2013 : case PHP_PG_CMD_TUPLES:
2014 : #if HAVE_PQCMDTUPLES
2015 1 : Z_LVAL_P(return_value) = atoi(PQcmdTuples(pgsql_result));
2016 : #else
2017 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not supported under this build");
2018 : Z_LVAL_P(return_value) = 0;
2019 : #endif
2020 1 : break;
2021 : default:
2022 0 : RETURN_FALSE;
2023 : }
2024 23 : Z_TYPE_P(return_value) = IS_LONG;
2025 : }
2026 : /* }}} */
2027 :
2028 : /* {{{ proto int pg_num_rows(resource result)
2029 : Return the number of rows in the result */
2030 : PHP_FUNCTION(pg_num_rows)
2031 16 : {
2032 16 : php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_NUM_ROWS);
2033 16 : }
2034 : /* }}} */
2035 :
2036 : /* {{{ proto int pg_num_fields(resource result)
2037 : Return the number of fields in the result */
2038 : PHP_FUNCTION(pg_num_fields)
2039 7 : {
2040 7 : php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_NUM_FIELDS);
2041 7 : }
2042 : /* }}} */
2043 :
2044 : #if HAVE_PQCMDTUPLES
2045 : /* {{{ proto int pg_affected_rows(resource result)
2046 : Returns the number of affected tuples */
2047 : PHP_FUNCTION(pg_affected_rows)
2048 1 : {
2049 1 : php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_CMD_TUPLES);
2050 1 : }
2051 : /* }}} */
2052 : #endif
2053 :
2054 : /* {{{ proto string pg_last_notice(resource connection)
2055 : Returns the last notice set by the backend */
2056 : PHP_FUNCTION(pg_last_notice)
2057 3 : {
2058 : zval *pgsql_link;
2059 : PGconn *pg_link;
2060 3 : int id = -1;
2061 : php_pgsql_notice **notice;
2062 :
2063 3 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pgsql_link) == FAILURE) {
2064 0 : return;
2065 : }
2066 : /* Just to check if user passed valid resoruce */
2067 3 : ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
2068 :
2069 3 : if (zend_hash_index_find(&PGG(notices), Z_RESVAL_P(pgsql_link), (void **)¬ice) == FAILURE) {
2070 0 : RETURN_FALSE;
2071 : }
2072 3 : RETURN_STRINGL((*notice)->message, (*notice)->len, 1);
2073 : }
2074 : /* }}} */
2075 :
2076 : /* {{{ get_field_name
2077 : */
2078 : static char *get_field_name(PGconn *pgsql, Oid oid, HashTable *list TSRMLS_DC)
2079 7 : {
2080 : PGresult *result;
2081 7 : smart_str str = {0};
2082 : zend_rsrc_list_entry *field_type;
2083 7 : char *ret=NULL;
2084 :
2085 : /* try to lookup the type in the resource list */
2086 7 : smart_str_appends(&str, "pgsql_oid_");
2087 7 : smart_str_append_unsigned(&str, oid);
2088 7 : smart_str_0(&str);
2089 :
2090 7 : if (zend_hash_find(list,str.c,str.len+1,(void **) &field_type)==SUCCESS) {
2091 0 : ret = estrdup((char *)field_type->ptr);
2092 : } else { /* hash all oid's */
2093 : int i,num_rows;
2094 : int oid_offset,name_offset;
2095 : char *tmp_oid, *end_ptr, *tmp_name;
2096 : zend_rsrc_list_entry new_oid_entry;
2097 :
2098 7 : if ((result = PQexec(pgsql,"select oid,typname from pg_type")) == NULL || PQresultStatus(result) != PGRES_TUPLES_OK) {
2099 0 : if (result) {
2100 0 : PQclear(result);
2101 : }
2102 0 : smart_str_free(&str);
2103 0 : return STR_EMPTY_ALLOC();
2104 : }
2105 7 : num_rows = PQntuples(result);
2106 7 : oid_offset = PQfnumber(result,"oid");
2107 7 : name_offset = PQfnumber(result,"typname");
2108 :
2109 1645 : for (i=0; i<num_rows; i++) {
2110 1638 : if ((tmp_oid = PQgetvalue(result,i,oid_offset))==NULL) {
2111 0 : continue;
2112 : }
2113 :
2114 1638 : str.len = 0;
2115 1638 : smart_str_appends(&str, "pgsql_oid_");
2116 1638 : smart_str_appends(&str, tmp_oid);
2117 1638 : smart_str_0(&str);
2118 :
2119 1638 : if ((tmp_name = PQgetvalue(result,i,name_offset))==NULL) {
2120 0 : continue;
2121 : }
2122 1638 : Z_TYPE(new_oid_entry) = le_string;
2123 1638 : new_oid_entry.ptr = estrdup(tmp_name);
2124 1638 : zend_hash_update(list,str.c,str.len+1,(void *) &new_oid_entry, sizeof(zend_rsrc_list_entry), NULL);
2125 1638 : if (!ret && strtoul(tmp_oid, &end_ptr, 10)==oid) {
2126 7 : ret = estrdup(tmp_name);
2127 : }
2128 : }
2129 7 : PQclear(result);
2130 : }
2131 :
2132 7 : smart_str_free(&str);
2133 7 : return ret;
2134 : }
2135 : /* }}} */
2136 :
2137 : #ifdef HAVE_PQFTABLE
2138 : /* {{{ proto mixed pg_field_table(resource result, int field_number[, bool oid_only])
2139 : Returns the name of the table field belongs to, or table's oid if oid_only is true */
2140 : PHP_FUNCTION(pg_field_table)
2141 0 : {
2142 : zval *result;
2143 : pgsql_result_handle *pg_result;
2144 0 : long fnum = -1;
2145 0 : zend_bool return_oid = 0;
2146 : Oid oid;
2147 0 : smart_str hash_key = {0};
2148 : char *table_name;
2149 : zend_rsrc_list_entry *field_table;
2150 :
2151 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|b", &result, &fnum, &return_oid) == FAILURE) {
2152 0 : return;
2153 : }
2154 :
2155 0 : ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2156 :
2157 0 : if (fnum < 0 || fnum >= PQnfields(pg_result->result)) {
2158 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad field offset specified");
2159 0 : RETURN_FALSE;
2160 : }
2161 :
2162 0 : oid = PQftable(pg_result->result, fnum);
2163 :
2164 0 : if (InvalidOid == oid) {
2165 0 : RETURN_FALSE;
2166 : }
2167 :
2168 :
2169 0 : if (return_oid) {
2170 : #if UINT_MAX > LONG_MAX /* Oid is unsigned int, we don't need this code, where LONG is wider */
2171 0 : if (oid > LONG_MAX) {
2172 0 : smart_str oidstr = {0};
2173 0 : smart_str_append_unsigned(&oidstr, oid);
2174 0 : smart_str_0(&oidstr);
2175 0 : RETURN_STRINGL(oidstr.c, oidstr.len, 0);
2176 : } else
2177 : #endif
2178 0 : RETURN_LONG((long)oid);
2179 : }
2180 :
2181 : /* try to lookup the table name in the resource list */
2182 0 : smart_str_appends(&hash_key, "pgsql_table_oid_");
2183 0 : smart_str_append_unsigned(&hash_key, oid);
2184 0 : smart_str_0(&hash_key);
2185 :
2186 0 : if (zend_hash_find(&EG(regular_list), hash_key.c, hash_key.len+1, (void **) &field_table) == SUCCESS) {
2187 0 : smart_str_free(&hash_key);
2188 0 : RETURN_STRING((char *)field_table->ptr, 1);
2189 : } else { /* Not found, lookup by querying PostgreSQL system tables */
2190 : PGresult *tmp_res;
2191 0 : smart_str querystr = {0};
2192 : zend_rsrc_list_entry new_field_table;
2193 :
2194 0 : smart_str_appends(&querystr, "select relname from pg_class where oid=");
2195 0 : smart_str_append_unsigned(&querystr, oid);
2196 0 : smart_str_0(&querystr);
2197 :
2198 :
2199 0 : if ((tmp_res = PQexec(pg_result->conn, querystr.c)) == NULL || PQresultStatus(tmp_res) != PGRES_TUPLES_OK) {
2200 0 : if (tmp_res) {
2201 0 : PQclear(tmp_res);
2202 : }
2203 0 : smart_str_free(&querystr);
2204 0 : smart_str_free(&hash_key);
2205 0 : RETURN_FALSE;
2206 : }
2207 :
2208 0 : smart_str_free(&querystr);
2209 :
2210 0 : if ((table_name = PQgetvalue(tmp_res, 0, 0)) == NULL) {
2211 0 : PQclear(tmp_res);
2212 0 : smart_str_free(&hash_key);
2213 0 : RETURN_FALSE;
2214 : }
2215 :
2216 0 : Z_TYPE(new_field_table) = le_string;
2217 0 : new_field_table.ptr = estrdup(table_name);
2218 0 : zend_hash_update(&EG(regular_list), hash_key.c, hash_key.len+1, (void *) &new_field_table, sizeof(zend_rsrc_list_entry), NULL);
2219 :
2220 0 : smart_str_free(&hash_key);
2221 0 : PQclear(tmp_res);
2222 0 : RETURN_STRING(table_name, 1);
2223 : }
2224 :
2225 : }
2226 : /* }}} */
2227 : #endif
2228 :
2229 : #define PHP_PG_FIELD_NAME 1
2230 : #define PHP_PG_FIELD_SIZE 2
2231 : #define PHP_PG_FIELD_TYPE 3
2232 : #define PHP_PG_FIELD_TYPE_OID 4
2233 :
2234 : /* {{{ php_pgsql_get_field_info
2235 : */
2236 : static void php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
2237 21 : {
2238 : zval *result;
2239 : long field;
2240 : PGresult *pgsql_result;
2241 : pgsql_result_handle *pg_result;
2242 : Oid oid;
2243 :
2244 21 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &result, &field) == FAILURE) {
2245 0 : return;
2246 : }
2247 :
2248 21 : ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2249 :
2250 21 : pgsql_result = pg_result->result;
2251 :
2252 21 : if (field < 0 || field >= PQnfields(pgsql_result)) {
2253 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad field offset specified");
2254 0 : RETURN_FALSE;
2255 : }
2256 :
2257 21 : switch (entry_type) {
2258 : case PHP_PG_FIELD_NAME:
2259 7 : Z_STRVAL_P(return_value) = PQfname(pgsql_result, field);
2260 7 : Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
2261 7 : Z_STRVAL_P(return_value) = estrndup(Z_STRVAL_P(return_value),Z_STRLEN_P(return_value));
2262 7 : Z_TYPE_P(return_value) = IS_STRING;
2263 7 : break;
2264 : case PHP_PG_FIELD_SIZE:
2265 7 : Z_LVAL_P(return_value) = PQfsize(pgsql_result, field);
2266 7 : Z_TYPE_P(return_value) = IS_LONG;
2267 7 : break;
2268 : case PHP_PG_FIELD_TYPE:
2269 7 : Z_STRVAL_P(return_value) = get_field_name(pg_result->conn, PQftype(pgsql_result, field), &EG(regular_list) TSRMLS_CC);
2270 7 : Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
2271 7 : Z_TYPE_P(return_value) = IS_STRING;
2272 7 : break;
2273 : case PHP_PG_FIELD_TYPE_OID:
2274 :
2275 0 : oid = PQftype(pgsql_result, field);
2276 : #if UINT_MAX > LONG_MAX
2277 0 : if (oid > LONG_MAX) {
2278 0 : smart_str s = {0};
2279 0 : smart_str_append_unsigned(&s, oid);
2280 0 : smart_str_0(&s);
2281 0 : Z_STRVAL_P(return_value) = s.c;
2282 0 : Z_STRLEN_P(return_value) = s.len;
2283 0 : Z_TYPE_P(return_value) = IS_STRING;
2284 : } else
2285 : #endif
2286 : {
2287 0 : Z_LVAL_P(return_value) = (long)oid;
2288 0 : Z_TYPE_P(return_value) = IS_LONG;
2289 : }
2290 0 : break;
2291 : default:
2292 0 : RETURN_FALSE;
2293 : }
2294 : }
2295 : /* }}} */
2296 :
2297 : /* {{{ proto string pg_field_name(resource result, int field_number)
2298 : Returns the name of the field */
2299 : PHP_FUNCTION(pg_field_name)
2300 7 : {
2301 7 : php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_FIELD_NAME);
2302 7 : }
2303 : /* }}} */
2304 :
2305 : /* {{{ proto int pg_field_size(resource result, int field_number)
2306 : Returns the internal size of the field */
2307 : PHP_FUNCTION(pg_field_size)
2308 7 : {
2309 7 : php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_FIELD_SIZE);
2310 7 : }
2311 : /* }}} */
2312 :
2313 : /* {{{ proto string pg_field_type(resource result, int field_number)
2314 : Returns the type name for the given field */
2315 : PHP_FUNCTION(pg_field_type)
2316 7 : {
2317 7 : php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_FIELD_TYPE);
2318 7 : }
2319 : /* }}} */
2320 :
2321 :
2322 : /* {{{ proto string pg_field_type_oid(resource result, int field_number)
2323 : Returns the type oid for the given field */
2324 : PHP_FUNCTION(pg_field_type_oid)
2325 0 : {
2326 0 : php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_FIELD_TYPE_OID);
2327 0 : }
2328 : /* }}} */
2329 :
2330 : /* {{{ proto int pg_field_num(resource result, string field_name)
2331 : Returns the field number of the named field */
2332 : PHP_FUNCTION(pg_field_num)
2333 6 : {
2334 : zval *result;
2335 : char *field;
2336 : int field_len;
2337 : PGresult *pgsql_result;
2338 : pgsql_result_handle *pg_result;
2339 :
2340 6 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &result, &field, &field_len) == FAILURE) {
2341 0 : return;
2342 : }
2343 :
2344 6 : ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2345 :
2346 6 : pgsql_result = pg_result->result;
2347 :
2348 6 : Z_LVAL_P(return_value) = PQfnumber(pgsql_result, field);
2349 6 : Z_TYPE_P(return_value) = IS_LONG;
2350 : }
2351 : /* }}} */
2352 :
2353 : /* {{{ proto mixed pg_fetch_result(resource result, [int row_number,] mixed field_name)
2354 : Returns values from a result identifier */
2355 : PHP_FUNCTION(pg_fetch_result)
2356 5618 : {
2357 5618 : zval *result, **field=NULL;
2358 : long row;
2359 : PGresult *pgsql_result;
2360 : pgsql_result_handle *pg_result;
2361 5618 : int field_offset, pgsql_row, argc = ZEND_NUM_ARGS();
2362 :
2363 5618 : if (argc == 2) {
2364 2 : if (zend_parse_parameters(argc TSRMLS_CC, "rZ", &result, &field) == FAILURE) {
2365 0 : return;
2366 : }
2367 : } else {
2368 5616 : if (zend_parse_parameters(argc TSRMLS_CC, "rlZ", &result, &row, &field) == FAILURE) {
2369 0 : return;
2370 : }
2371 : }
2372 :
2373 5618 : ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2374 :
2375 5618 : pgsql_result = pg_result->result;
2376 5618 : if (argc == 2) {
2377 2 : if (pg_result->row < 0) {
2378 0 : pg_result->row = 0;
2379 : }
2380 2 : pgsql_row = pg_result->row;
2381 2 : if (pgsql_row >= PQntuples(pgsql_result)) {
2382 0 : RETURN_FALSE;
2383 : }
2384 : } else {
2385 5616 : pgsql_row = row;
2386 5616 : if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
2387 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to jump to row %ld on PostgreSQL result index %ld",
2388 : row, Z_LVAL_P(result));
2389 0 : RETURN_FALSE;
2390 : }
2391 : }
2392 5618 : switch(Z_TYPE_PP(field)) {
2393 : case IS_STRING:
2394 0 : field_offset = PQfnumber(pgsql_result, Z_STRVAL_PP(field));
2395 0 : break;
2396 : default:
2397 5618 : convert_to_long_ex(field);
2398 5618 : field_offset = Z_LVAL_PP(field);
2399 : break;
2400 : }
2401 5618 : if (field_offset<0 || field_offset>=PQnfields(pgsql_result)) {
2402 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset specified");
2403 0 : RETURN_FALSE;
2404 : }
2405 :
2406 5618 : if (PQgetisnull(pgsql_result, pgsql_row, field_offset)) {
2407 0 : Z_TYPE_P(return_value) = IS_NULL;
2408 : } else {
2409 5618 : char *value = PQgetvalue(pgsql_result, pgsql_row, field_offset);
2410 5618 : int value_len = PQgetlength(pgsql_result, pgsql_row, field_offset);
2411 5618 : ZVAL_STRINGL(return_value, value, value_len, 1);
2412 : }
2413 : }
2414 : /* }}} */
2415 :
2416 : /* {{{ void php_pgsql_fetch_hash */
2417 : static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, long result_type, int into_object)
2418 16865 : {
2419 16865 : zval *result, *zrow = NULL;
2420 : PGresult *pgsql_result;
2421 : pgsql_result_handle *pg_result;
2422 : int i, num_fields, pgsql_row, use_row;
2423 16865 : long row = -1;
2424 : char *field_name;
2425 16865 : zval *ctor_params = NULL;
2426 16865 : zend_class_entry *ce = NULL;
2427 :
2428 16865 : if (into_object) {
2429 5618 : char *class_name = NULL;
2430 : int class_name_len;
2431 :
2432 5618 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|z!sz", &result, &zrow, &class_name, &class_name_len, &ctor_params) == FAILURE) {
2433 0 : return;
2434 : }
2435 5618 : if (!class_name) {
2436 5617 : ce = zend_standard_class_def;
2437 : } else {
2438 1 : ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
2439 : }
2440 5618 : if (!ce) {
2441 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not find class '%s'", class_name);
2442 0 : return;
2443 : }
2444 5618 : result_type = PGSQL_ASSOC;
2445 : } else {
2446 11247 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|z!l", &result, &zrow, &result_type) == FAILURE) {
2447 0 : return;
2448 : }
2449 : }
2450 16865 : if (zrow == NULL) {
2451 5629 : row = -1;
2452 : } else {
2453 11236 : convert_to_long(zrow);
2454 11236 : row = Z_LVAL_P(zrow);
2455 : }
2456 16865 : use_row = ZEND_NUM_ARGS() > 1 && row != -1;
2457 :
2458 16865 : if (!(result_type & PGSQL_BOTH)) {
2459 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid result type");
2460 0 : RETURN_FALSE;
2461 : }
2462 :
2463 16865 : ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2464 :
2465 16865 : pgsql_result = pg_result->result;
2466 :
2467 16865 : if (use_row) {
2468 11236 : pgsql_row = row;
2469 11236 : pg_result->row = pgsql_row;
2470 11236 : if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
2471 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to jump to row %ld on PostgreSQL result index %ld",
2472 : row, Z_LVAL_P(result));
2473 0 : RETURN_FALSE;
2474 : }
2475 : } else {
2476 : /* If 2nd param is NULL, use internal row counter to access next row */
2477 5629 : pgsql_row = pg_result->row;
2478 5629 : if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
2479 5611 : RETURN_FALSE;
2480 : }
2481 18 : pg_result->row++;
2482 : }
2483 :
2484 11254 : array_init(return_value);
2485 44993 : for (i = 0, num_fields = PQnfields(pgsql_result); i < num_fields; i++) {
2486 33739 : if (PQgetisnull(pgsql_result, pgsql_row, i)) {
2487 11241 : if (result_type & PGSQL_NUM) {
2488 11232 : add_index_null(return_value, i);
2489 : }
2490 11241 : if (result_type & PGSQL_ASSOC) {
2491 10 : field_name = PQfname(pgsql_result, i);
2492 10 : add_assoc_null(return_value, field_name);
2493 : }
2494 : } else {
2495 22498 : char *element = PQgetvalue(pgsql_result, pgsql_row, i);
2496 22498 : if (element) {
2497 : char *data;
2498 : int data_len;
2499 22498 : int should_copy=0;
2500 22498 : const uint element_len = strlen(element);
2501 :
2502 22498 : if (PG(magic_quotes_runtime)) {
2503 0 : data = php_addslashes(element, element_len, &data_len, 0 TSRMLS_CC);
2504 : } else {
2505 22498 : data = safe_estrndup(element, element_len);
2506 22498 : data_len = element_len;
2507 : }
2508 :
2509 22498 : if (result_type & PGSQL_NUM) {
2510 22468 : add_index_stringl(return_value, i, data, data_len, should_copy);
2511 22468 : should_copy=1;
2512 : }
2513 :
2514 22498 : if (result_type & PGSQL_ASSOC) {
2515 34 : field_name = PQfname(pgsql_result, i);
2516 34 : add_assoc_stringl(return_value, field_name, data, data_len, should_copy);
2517 : }
2518 : }
2519 : }
2520 : }
2521 :
2522 11254 : if (into_object) {
2523 9 : zval dataset = *return_value;
2524 : zend_fcall_info fci;
2525 : zend_fcall_info_cache fcc;
2526 : zval *retval_ptr;
2527 :
2528 9 : object_and_properties_init(return_value, ce, NULL);
2529 9 : zend_merge_properties(return_value, Z_ARRVAL(dataset), 1 TSRMLS_CC);
2530 :
2531 9 : if (ce->constructor) {
2532 1 : fci.size = sizeof(fci);
2533 1 : fci.function_table = &ce->function_table;
2534 1 : fci.function_name = NULL;
2535 1 : fci.symbol_table = NULL;
2536 1 : fci.object_ptr = return_value;
2537 1 : fci.retval_ptr_ptr = &retval_ptr;
2538 2 : if (ctor_params && Z_TYPE_P(ctor_params) != IS_NULL) {
2539 1 : if (Z_TYPE_P(ctor_params) == IS_ARRAY) {
2540 1 : HashTable *ht = Z_ARRVAL_P(ctor_params);
2541 : Bucket *p;
2542 :
2543 1 : fci.param_count = 0;
2544 1 : fci.params = safe_emalloc(sizeof(zval*), ht->nNumOfElements, 0);
2545 1 : p = ht->pListHead;
2546 4 : while (p != NULL) {
2547 2 : fci.params[fci.param_count++] = (zval**)p->pData;
2548 2 : p = p->pListNext;
2549 : }
2550 : } else {
2551 : /* Two problems why we throw exceptions here: PHP is typeless
2552 : * and hence passing one argument that's not an array could be
2553 : * by mistake and the other way round is possible, too. The
2554 : * single value is an array. Also we'd have to make that one
2555 : * argument passed by reference.
2556 : */
2557 0 : zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Parameter ctor_params must be an array", 0 TSRMLS_CC);
2558 0 : return;
2559 : }
2560 : } else {
2561 0 : fci.param_count = 0;
2562 0 : fci.params = NULL;
2563 : }
2564 1 : fci.no_separation = 1;
2565 :
2566 1 : fcc.initialized = 1;
2567 1 : fcc.function_handler = ce->constructor;
2568 1 : fcc.calling_scope = EG(scope);
2569 1 : fcc.called_scope = Z_OBJCE_P(return_value);
2570 1 : fcc.object_ptr = return_value;
2571 :
2572 1 : if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
2573 0 : zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Could not execute %s::%s()", ce->name, ce->constructor->common.function_name);
2574 : } else {
2575 1 : if (retval_ptr) {
2576 1 : zval_ptr_dtor(&retval_ptr);
2577 : }
2578 : }
2579 1 : if (fci.params) {
2580 1 : efree(fci.params);
2581 : }
2582 8 : } else if (ctor_params) {
2583 0 : zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 0 TSRMLS_CC, "Class %s does not have a constructor hence you cannot use ctor_params", ce->name);
2584 : }
2585 : }
2586 : }
2587 : /* }}} */
2588 :
2589 : /* {{{ proto array pg_fetch_row(resource result [, int row [, int result_type]])
2590 : Get a row as an enumerated array */
2591 : PHP_FUNCTION(pg_fetch_row)
2592 5618 : {
2593 5618 : php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_NUM, 0);
2594 5618 : }
2595 : /* }}} */
2596 :
2597 : /* {{{ proto array pg_fetch_assoc(resource result [, int row])
2598 : Fetch a row as an assoc array */
2599 : PHP_FUNCTION(pg_fetch_assoc)
2600 5 : {
2601 : /* pg_fetch_assoc() is added from PHP 4.3.0. It should raise error, when
2602 : there is 3rd parameter */
2603 5 : if (ZEND_NUM_ARGS() > 2)
2604 0 : WRONG_PARAM_COUNT;
2605 5 : php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_ASSOC, 0);
2606 : }
2607 : /* }}} */
2608 :
2609 : /* {{{ proto array pg_fetch_array(resource result [, int row [, int result_type]])
2610 : Fetch a row as an array */
2611 : PHP_FUNCTION(pg_fetch_array)
2612 5624 : {
2613 5624 : php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_BOTH, 0);
2614 5624 : }
2615 : /* }}} */
2616 :
2617 : /* {{{ proto object pg_fetch_object(resource result [, int row [, string class_name [, NULL|array ctor_params]]])
2618 : Fetch a row as an object */
2619 : PHP_FUNCTION(pg_fetch_object)
2620 5618 : {
2621 : /* pg_fetch_object() allowed result_type used to be. 3rd parameter
2622 : must be allowed for compatibility */
2623 5618 : php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_ASSOC, 1);
2624 5618 : }
2625 : /* }}} */
2626 :
2627 : /* {{{ proto array pg_fetch_all(resource result)
2628 : Fetch all rows into array */
2629 : PHP_FUNCTION(pg_fetch_all)
2630 3 : {
2631 : zval *result;
2632 : PGresult *pgsql_result;
2633 : pgsql_result_handle *pg_result;
2634 :
2635 3 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) == FAILURE) {
2636 0 : return;
2637 : }
2638 :
2639 3 : ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2640 :
2641 3 : pgsql_result = pg_result->result;
2642 3 : array_init(return_value);
2643 3 : if (php_pgsql_result2array(pgsql_result, return_value TSRMLS_CC) == FAILURE) {
2644 0 : zval_dtor(return_value);
2645 0 : RETURN_FALSE;
2646 : }
2647 : }
2648 : /* }}} */
2649 :
2650 : /* {{{ proto array pg_fetch_all_columns(resource result [, int column_number])
2651 : Fetch all rows into array */
2652 : PHP_FUNCTION(pg_fetch_all_columns)
2653 0 : {
2654 : zval *result;
2655 : PGresult *pgsql_result;
2656 : pgsql_result_handle *pg_result;
2657 0 : unsigned long colno=0;
2658 : int pg_numrows, pg_row;
2659 : size_t num_fields;
2660 :
2661 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &result, &colno) == FAILURE) {
2662 0 : RETURN_FALSE;
2663 : }
2664 :
2665 0 : ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2666 :
2667 0 : pgsql_result = pg_result->result;
2668 :
2669 0 : num_fields = PQnfields(pgsql_result);
2670 0 : if (colno >= num_fields || colno < 0) {
2671 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid column number '%ld'", colno);
2672 0 : RETURN_FALSE;
2673 : }
2674 :
2675 0 : array_init(return_value);
2676 :
2677 0 : if ((pg_numrows = PQntuples(pgsql_result)) <= 0) {
2678 0 : return;
2679 : }
2680 :
2681 0 : for (pg_row = 0; pg_row < pg_numrows; pg_row++) {
2682 0 : if (PQgetisnull(pgsql_result, pg_row, colno)) {
2683 0 : add_next_index_null(return_value);
2684 : } else {
2685 0 : add_next_index_string(return_value, PQgetvalue(pgsql_result, pg_row, colno), 1);
2686 : }
2687 : }
2688 : }
2689 : /* }}} */
2690 :
2691 : /* {{{ proto bool pg_result_seek(resource result, int offset)
2692 : Set internal row offset */
2693 : PHP_FUNCTION(pg_result_seek)
2694 2 : {
2695 : zval *result;
2696 : long row;
2697 : pgsql_result_handle *pg_result;
2698 :
2699 2 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &result, &row) == FAILURE) {
2700 0 : return;
2701 : }
2702 :
2703 2 : ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2704 :
2705 2 : if (row < 0 || row >= PQntuples(pg_result->result)) {
2706 0 : RETURN_FALSE;
2707 : }
2708 :
2709 : /* seek to offset */
2710 2 : pg_result->row = row;
2711 2 : RETURN_TRUE;
2712 : }
2713 : /* }}} */
2714 :
2715 :
2716 : #define PHP_PG_DATA_LENGTH 1
2717 : #define PHP_PG_DATA_ISNULL 2
2718 :
2719 : /* {{{ php_pgsql_data_info
2720 : */
2721 : static void php_pgsql_data_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
2722 14 : {
2723 : zval *result, **field;
2724 : long row;
2725 : PGresult *pgsql_result;
2726 : pgsql_result_handle *pg_result;
2727 14 : int field_offset, pgsql_row, argc = ZEND_NUM_ARGS();
2728 :
2729 14 : if (argc == 2) {
2730 14 : if (zend_parse_parameters(argc TSRMLS_CC, "rZ", &result, &field) == FAILURE) {
2731 0 : return;
2732 : }
2733 : } else {
2734 0 : if (zend_parse_parameters(argc TSRMLS_CC, "rlZ", &result, &row, &field) == FAILURE) {
2735 0 : return;
2736 : }
2737 : }
2738 :
2739 14 : ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2740 :
2741 14 : pgsql_result = pg_result->result;
2742 14 : if (argc == 2) {
2743 14 : if (pg_result->row < 0) {
2744 0 : pg_result->row = 0;
2745 : }
2746 14 : pgsql_row = pg_result->row;
2747 14 : if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
2748 0 : RETURN_FALSE;
2749 : }
2750 : } else {
2751 0 : pgsql_row = row;
2752 0 : if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
2753 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to jump to row %ld on PostgreSQL result index %ld",
2754 : row, Z_LVAL_P(result));
2755 0 : RETURN_FALSE;
2756 : }
2757 : }
2758 :
2759 14 : switch(Z_TYPE_PP(field)) {
2760 : case IS_STRING:
2761 0 : convert_to_string_ex(field);
2762 0 : field_offset = PQfnumber(pgsql_result, Z_STRVAL_PP(field));
2763 0 : break;
2764 : default:
2765 14 : convert_to_long_ex(field);
2766 14 : field_offset = Z_LVAL_PP(field);
2767 : break;
2768 : }
2769 14 : if (field_offset < 0 || field_offset >= PQnfields(pgsql_result)) {
2770 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset specified");
2771 0 : RETURN_FALSE;
2772 : }
2773 :
2774 14 : switch (entry_type) {
2775 : case PHP_PG_DATA_LENGTH:
2776 7 : Z_LVAL_P(return_value) = PQgetlength(pgsql_result, pgsql_row, field_offset);
2777 7 : break;
2778 : case PHP_PG_DATA_ISNULL:
2779 7 : Z_LVAL_P(return_value) = PQgetisnull(pgsql_result, pgsql_row, field_offset);
2780 : break;
2781 : }
2782 14 : Z_TYPE_P(return_value) = IS_LONG;
2783 : }
2784 : /* }}} */
2785 :
2786 : /* {{{ proto int pg_field_prtlen(resource result, [int row,] mixed field_name_or_number)
2787 : Returns the printed length */
2788 : PHP_FUNCTION(pg_field_prtlen)
2789 7 : {
2790 7 : php_pgsql_data_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_DATA_LENGTH);
2791 7 : }
2792 : /* }}} */
2793 :
2794 : /* {{{ proto int pg_field_is_null(resource result, [int row,] mixed field_name_or_number)
2795 : Test if a field is NULL */
2796 : PHP_FUNCTION(pg_field_is_null)
2797 7 : {
2798 7 : php_pgsql_data_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_DATA_ISNULL);
2799 7 : }
2800 : /* }}} */
2801 :
2802 : /* {{{ proto bool pg_free_result(resource result)
2803 : Free result memory */
2804 : PHP_FUNCTION(pg_free_result)
2805 13 : {
2806 : zval *result;
2807 : pgsql_result_handle *pg_result;
2808 :
2809 13 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) == FAILURE) {
2810 0 : return;
2811 : }
2812 :
2813 13 : ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2814 13 : if (Z_LVAL_P(result) == 0) {
2815 0 : RETURN_FALSE;
2816 : }
2817 13 : zend_list_delete(Z_RESVAL_P(result));
2818 13 : RETURN_TRUE;
2819 : }
2820 : /* }}} */
2821 :
2822 : /* {{{ proto string pg_last_oid(resource result)
2823 : Returns the last object identifier */
2824 : PHP_FUNCTION(pg_last_oid)
2825 7 : {
2826 : zval *result;
2827 : PGresult *pgsql_result;
2828 : pgsql_result_handle *pg_result;
2829 : #ifdef HAVE_PQOIDVALUE
2830 : Oid oid;
2831 : #endif
2832 :
2833 7 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) == FAILURE) {
2834 0 : return;
2835 : }
2836 :
2837 7 : ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2838 7 : pgsql_result = pg_result->result;
2839 : #ifdef HAVE_PQOIDVALUE
2840 7 : oid = PQoidValue(pgsql_result);
2841 7 : if (oid == InvalidOid) {
2842 7 : RETURN_FALSE;
2843 : }
2844 0 : PGSQL_RETURN_OID(oid);
2845 : #else
2846 : Z_STRVAL_P(return_value) = (char *) PQoidStatus(pgsql_result);
2847 : if (Z_STRVAL_P(return_value)) {
2848 : RETURN_STRING(Z_STRVAL_P(return_value), 1);
2849 : }
2850 : RETURN_STRING("", 1);
2851 : #endif
2852 : }
2853 : /* }}} */
2854 :
2855 : /* {{{ proto bool pg_trace(string filename [, string mode [, resource connection]])
2856 : Enable tracing a PostgreSQL connection */
2857 : PHP_FUNCTION(pg_trace)
2858 1 : {
2859 1 : char *z_filename, *mode = "w";
2860 : int z_filename_len, mode_len;
2861 1 : zval *pgsql_link = NULL;
2862 1 : int id = -1, argc = ZEND_NUM_ARGS();
2863 : PGconn *pgsql;
2864 1 : FILE *fp = NULL;
2865 : php_stream *stream;
2866 1 : id = PGG(default_link);
2867 :
2868 1 : if (zend_parse_parameters(argc TSRMLS_CC, "s|sr", &z_filename, &z_filename_len, &mode, &mode_len, &pgsql_link) == FAILURE) {
2869 0 : return;
2870 : }
2871 :
2872 1 : if (argc < 3) {
2873 0 : CHECK_DEFAULT_LINK(id);
2874 : }
2875 :
2876 1 : if (pgsql_link == NULL && id == -1) {
2877 0 : RETURN_FALSE;
2878 : }
2879 :
2880 1 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
2881 :
2882 1 : stream = php_stream_open_wrapper(z_filename, mode, ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
2883 :
2884 1 : if (!stream) {
2885 0 : RETURN_FALSE;
2886 : }
2887 :
2888 1 : if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void**)&fp, REPORT_ERRORS)) {
2889 0 : php_stream_close(stream);
2890 0 : RETURN_FALSE;
2891 : }
2892 : php_stream_auto_cleanup(stream);
2893 1 : PQtrace(pgsql, fp);
2894 1 : RETURN_TRUE;
2895 : }
2896 : /* }}} */
2897 :
2898 : /* {{{ proto bool pg_untrace([resource connection])
2899 : Disable tracing of a PostgreSQL connection */
2900 : PHP_FUNCTION(pg_untrace)
2901 0 : {
2902 0 : zval *pgsql_link = NULL;
2903 0 : int id = -1, argc = ZEND_NUM_ARGS();
2904 : PGconn *pgsql;
2905 :
2906 0 : if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) {
2907 0 : return;
2908 : }
2909 :
2910 0 : if (argc == 0) {
2911 0 : id = PGG(default_link);
2912 0 : CHECK_DEFAULT_LINK(id);
2913 : }
2914 :
2915 0 : if (pgsql_link == NULL && id == -1) {
2916 0 : RETURN_FALSE;
2917 : }
2918 :
2919 0 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
2920 0 : PQuntrace(pgsql);
2921 0 : RETURN_TRUE;
2922 : }
2923 : /* }}} */
2924 :
2925 : /* {{{ proto mixed pg_lo_create([resource connection],[mixed large_object_oid])
2926 : Create a large object */
2927 : PHP_FUNCTION(pg_lo_create)
2928 3 : {
2929 3 : zval *pgsql_link = NULL, *oid = NULL;
2930 : PGconn *pgsql;
2931 3 : Oid pgsql_oid, wanted_oid = InvalidOid;
2932 3 : int id = -1, argc = ZEND_NUM_ARGS();
2933 :
2934 3 : if (zend_parse_parameters(argc TSRMLS_CC, "|zz", &pgsql_link, &oid) == FAILURE) {
2935 0 : return;
2936 : }
2937 :
2938 3 : if ((argc == 1) && (Z_TYPE_P(pgsql_link) != IS_RESOURCE)) {
2939 0 : oid = pgsql_link;
2940 0 : pgsql_link = NULL;
2941 : }
2942 :
2943 3 : if (pgsql_link == NULL) {
2944 0 : id = PGG(default_link);
2945 0 : CHECK_DEFAULT_LINK(id);
2946 0 : if (id == -1) {
2947 0 : RETURN_FALSE;
2948 : }
2949 : }
2950 :
2951 3 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
2952 :
2953 3 : if (oid) {
2954 : #ifndef HAVE_PG_LO_CREATE
2955 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "OID value passing not supported");
2956 : #else
2957 0 : switch (Z_TYPE_P(oid)) {
2958 : case IS_STRING:
2959 : {
2960 : char *end_ptr;
2961 0 : wanted_oid = (Oid)strtoul(Z_STRVAL_P(oid), &end_ptr, 10);
2962 0 : if ((Z_STRVAL_P(oid)+Z_STRLEN_P(oid)) != end_ptr) {
2963 : /* wrong integer format */
2964 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
2965 0 : RETURN_FALSE;
2966 : }
2967 : }
2968 0 : break;
2969 : case IS_LONG:
2970 0 : if (Z_LVAL_P(oid) < (long)InvalidOid) {
2971 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
2972 0 : RETURN_FALSE;
2973 : }
2974 0 : wanted_oid = (Oid)Z_LVAL_P(oid);
2975 0 : break;
2976 : default:
2977 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
2978 0 : RETURN_FALSE;
2979 : }
2980 0 : if ((pgsql_oid = lo_create(pgsql, wanted_oid)) == InvalidOid) {
2981 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create PostgreSQL large object");
2982 0 : RETURN_FALSE;
2983 : }
2984 :
2985 0 : PGSQL_RETURN_OID(pgsql_oid);
2986 : #endif
2987 : }
2988 :
2989 3 : if ((pgsql_oid = lo_creat(pgsql, INV_READ|INV_WRITE)) == InvalidOid) {
2990 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create PostgreSQL large object");
2991 0 : RETURN_FALSE;
2992 : }
2993 :
2994 3 : PGSQL_RETURN_OID(pgsql_oid);
2995 : }
2996 : /* }}} */
2997 :
2998 : /* {{{ proto bool pg_lo_unlink([resource connection,] string large_object_oid)
2999 : Delete a large object */
3000 : PHP_FUNCTION(pg_lo_unlink)
3001 3 : {
3002 3 : zval *pgsql_link = NULL;
3003 : long oid_long;
3004 : char *oid_string, *end_ptr;
3005 : int oid_strlen;
3006 : PGconn *pgsql;
3007 : Oid oid;
3008 3 : int id = -1;
3009 3 : int argc = ZEND_NUM_ARGS();
3010 :
3011 : /* accept string type since Oid type is unsigned int */
3012 3 : if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3013 : "rs", &pgsql_link, &oid_string, &oid_strlen) == SUCCESS) {
3014 2 : oid = (Oid)strtoul(oid_string, &end_ptr, 10);
3015 2 : if ((oid_string+oid_strlen) != end_ptr) {
3016 : /* wrong integer format */
3017 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
3018 0 : RETURN_FALSE;
3019 : }
3020 : }
3021 1 : else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3022 : "rl", &pgsql_link, &oid_long) == SUCCESS) {
3023 0 : if (oid_long <= InvalidOid) {
3024 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
3025 0 : RETURN_FALSE;
3026 : }
3027 0 : oid = (Oid)oid_long;
3028 : }
3029 1 : else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3030 : "s", &oid_string, &oid_strlen) == SUCCESS) {
3031 1 : oid = (Oid)strtoul(oid_string, &end_ptr, 10);
3032 1 : if ((oid_string+oid_strlen) != end_ptr) {
3033 : /* wrong integer format */
3034 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
3035 0 : RETURN_FALSE;
3036 : }
3037 1 : id = PGG(default_link);
3038 1 : CHECK_DEFAULT_LINK(id);
3039 : }
3040 0 : else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3041 : "l", &oid_long) == SUCCESS) {
3042 0 : if (oid_long <= InvalidOid) {
3043 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID is specified");
3044 0 : RETURN_FALSE;
3045 : }
3046 0 : oid = (Oid)oid_long;
3047 0 : id = PGG(default_link);
3048 0 : CHECK_DEFAULT_LINK(id);
3049 : }
3050 : else {
3051 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Requires 1 or 2 arguments");
3052 0 : RETURN_FALSE;
3053 : }
3054 3 : if (pgsql_link == NULL && id == -1) {
3055 0 : RETURN_FALSE;
3056 : }
3057 :
3058 3 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3059 :
3060 3 : if (lo_unlink(pgsql, oid) == -1) {
3061 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to delete PostgreSQL large object %u", oid);
3062 0 : RETURN_FALSE;
3063 : }
3064 3 : RETURN_TRUE;
3065 : }
3066 : /* }}} */
3067 :
3068 : /* {{{ proto resource pg_lo_open([resource connection,] int large_object_oid, string mode)
3069 : Open a large object and return fd */
3070 : PHP_FUNCTION(pg_lo_open)
3071 3 : {
3072 3 : zval *pgsql_link = NULL;
3073 : long oid_long;
3074 : char *oid_string, *end_ptr, *mode_string;
3075 : int oid_strlen, mode_strlen;
3076 : PGconn *pgsql;
3077 : Oid oid;
3078 3 : int id = -1, pgsql_mode=0, pgsql_lofd;
3079 3 : int create=0;
3080 : pgLofp *pgsql_lofp;
3081 3 : int argc = ZEND_NUM_ARGS();
3082 :
3083 : /* accept string type since Oid is unsigned int */
3084 3 : if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3085 : "rss", &pgsql_link, &oid_string, &oid_strlen, &mode_string, &mode_strlen) == SUCCESS) {
3086 3 : oid = (Oid)strtoul(oid_string, &end_ptr, 10);
3087 3 : if ((oid_string+oid_strlen) != end_ptr) {
3088 : /* wrong integer format */
3089 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
3090 0 : RETURN_FALSE;
3091 : }
3092 : }
3093 0 : else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3094 : "rls", &pgsql_link, &oid_long, &mode_string, &mode_strlen) == SUCCESS) {
3095 0 : if (oid_long <= InvalidOid) {
3096 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
3097 0 : RETURN_FALSE;
3098 : }
3099 0 : oid = (Oid)oid_long;
3100 : }
3101 0 : else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3102 : "ss", &oid_string, &oid_strlen, &mode_string, &mode_strlen) == SUCCESS) {
3103 0 : oid = (Oid)strtoul(oid_string, &end_ptr, 10);
3104 0 : if ((oid_string+oid_strlen) != end_ptr) {
3105 : /* wrong integer format */
3106 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
3107 0 : RETURN_FALSE;
3108 : }
3109 0 : id = PGG(default_link);
3110 0 : CHECK_DEFAULT_LINK(id);
3111 : }
3112 0 : else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3113 : "ls", &oid_long, &mode_string, &mode_strlen) == SUCCESS) {
3114 0 : if (oid_long <= InvalidOid) {
3115 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
3116 0 : RETURN_FALSE;
3117 : }
3118 0 : oid = (Oid)oid_long;
3119 0 : id = PGG(default_link);
3120 0 : CHECK_DEFAULT_LINK(id);
3121 : }
3122 : else {
3123 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Requires 1 or 2 arguments");
3124 0 : RETURN_FALSE;
3125 : }
3126 3 : if (pgsql_link == NULL && id == -1) {
3127 0 : RETURN_FALSE;
3128 : }
3129 :
3130 3 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3131 :
3132 : /* r/w/+ is little bit more PHP-like than INV_READ/INV_WRITE and a lot of
3133 : faster to type. Unfortunately, doesn't behave the same way as fopen()...
3134 : (Jouni)
3135 : */
3136 :
3137 3 : if (strchr(mode_string, 'r') == mode_string) {
3138 0 : pgsql_mode |= INV_READ;
3139 0 : if (strchr(mode_string, '+') == mode_string+1) {
3140 0 : pgsql_mode |= INV_WRITE;
3141 : }
3142 : }
3143 3 : if (strchr(mode_string, 'w') == mode_string) {
3144 3 : pgsql_mode |= INV_WRITE;
3145 3 : create = 1;
3146 3 : if (strchr(mode_string, '+') == mode_string+1) {
3147 0 : pgsql_mode |= INV_READ;
3148 : }
3149 : }
3150 :
3151 3 : pgsql_lofp = (pgLofp *) emalloc(sizeof(pgLofp));
3152 :
3153 3 : if ((pgsql_lofd = lo_open(pgsql, oid, pgsql_mode)) == -1) {
3154 0 : if (create) {
3155 0 : if ((oid = lo_creat(pgsql, INV_READ|INV_WRITE)) == 0) {
3156 0 : efree(pgsql_lofp);
3157 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create PostgreSQL large object");
3158 0 : RETURN_FALSE;
3159 : } else {
3160 0 : if ((pgsql_lofd = lo_open(pgsql, oid, pgsql_mode)) == -1) {
3161 0 : if (lo_unlink(pgsql, oid) == -1) {
3162 0 : efree(pgsql_lofp);
3163 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Something is really messed up! Your database is badly corrupted in a way NOT related to PHP");
3164 0 : RETURN_FALSE;
3165 : }
3166 0 : efree(pgsql_lofp);
3167 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open PostgreSQL large object");
3168 0 : RETURN_FALSE;
3169 : } else {
3170 0 : pgsql_lofp->conn = pgsql;
3171 0 : pgsql_lofp->lofd = pgsql_lofd;
3172 0 : Z_LVAL_P(return_value) = zend_list_insert(pgsql_lofp, le_lofp);
3173 0 : Z_TYPE_P(return_value) = IS_LONG;
3174 : }
3175 : }
3176 : } else {
3177 0 : efree(pgsql_lofp);
3178 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open PostgreSQL large object");
3179 0 : RETURN_FALSE;
3180 : }
3181 : } else {
3182 3 : pgsql_lofp->conn = pgsql;
3183 3 : pgsql_lofp->lofd = pgsql_lofd;
3184 3 : ZEND_REGISTER_RESOURCE(return_value, pgsql_lofp, le_lofp);
3185 : }
3186 : }
3187 : /* }}} */
3188 :
3189 : /* {{{ proto bool pg_lo_close(resource large_object)
3190 : Close a large object */
3191 : PHP_FUNCTION(pg_lo_close)
3192 3 : {
3193 : zval *pgsql_lofp;
3194 : pgLofp *pgsql;
3195 :
3196 3 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pgsql_lofp) == FAILURE) {
3197 0 : return;
3198 : }
3199 :
3200 3 : ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_lofp, -1, "PostgreSQL large object", le_lofp);
3201 :
3202 3 : if (lo_close((PGconn *)pgsql->conn, pgsql->lofd) < 0) {
3203 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to close PostgreSQL large object descriptor %d", pgsql->lofd);
3204 0 : RETVAL_FALSE;
3205 : } else {
3206 3 : RETVAL_TRUE;
3207 : }
3208 :
3209 3 : zend_list_delete(Z_RESVAL_P(pgsql_lofp));
3210 3 : return;
3211 : }
3212 : /* }}} */
3213 :
3214 : #define PGSQL_LO_READ_BUF_SIZE 8192
3215 :
3216 : /* {{{ proto string pg_lo_read(resource large_object [, int len])
3217 : Read a large object */
3218 : PHP_FUNCTION(pg_lo_read)
3219 1 : {
3220 : zval *pgsql_id;
3221 : long len;
3222 1 : int buf_len = PGSQL_LO_READ_BUF_SIZE, nbytes, argc = ZEND_NUM_ARGS();
3223 : char *buf;
3224 : pgLofp *pgsql;
3225 :
3226 1 : if (zend_parse_parameters(argc TSRMLS_CC, "r|l", &pgsql_id, &len) == FAILURE) {
3227 0 : return;
3228 : }
3229 :
3230 1 : ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_id, -1, "PostgreSQL large object", le_lofp);
3231 :
3232 1 : if (argc > 1) {
3233 1 : buf_len = len;
3234 : }
3235 :
3236 1 : buf = (char *) safe_emalloc(sizeof(char), (buf_len+1), 0);
3237 1 : if ((nbytes = lo_read((PGconn *)pgsql->conn, pgsql->lofd, buf, buf_len))<0) {
3238 0 : efree(buf);
3239 0 : RETURN_FALSE;
3240 : }
3241 :
3242 1 : buf[nbytes] = '\0';
3243 1 : RETURN_STRINGL(buf, nbytes, 0);
3244 : }
3245 : /* }}} */
3246 :
3247 : /* {{{ proto int pg_lo_write(resource large_object, string buf [, int len])
3248 : Write a large object */
3249 : PHP_FUNCTION(pg_lo_write)
3250 1 : {
3251 : zval *pgsql_id;
3252 : char *str;
3253 : long z_len;
3254 : int str_len, nbytes;
3255 : int len;
3256 : pgLofp *pgsql;
3257 1 : int argc = ZEND_NUM_ARGS();
3258 :
3259 1 : if (zend_parse_parameters(argc TSRMLS_CC, "rs|l", &pgsql_id, &str, &str_len, &z_len) == FAILURE) {
3260 0 : return;
3261 : }
3262 :
3263 1 : if (argc > 2) {
3264 0 : if (z_len > str_len) {
3265 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot write more than buffer size %d. Tried to write %ld", str_len, z_len);
3266 0 : RETURN_FALSE;
3267 : }
3268 0 : if (z_len < 0) {
3269 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Buffer size must be larger than 0, but %ld was specified", z_len);
3270 0 : RETURN_FALSE;
3271 : }
3272 0 : len = z_len;
3273 : }
3274 : else {
3275 1 : len = str_len;
3276 : }
3277 :
3278 1 : ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_id, -1, "PostgreSQL large object", le_lofp);
3279 :
3280 1 : if ((nbytes = lo_write((PGconn *)pgsql->conn, pgsql->lofd, str, len)) == -1) {
3281 0 : RETURN_FALSE;
3282 : }
3283 :
3284 1 : RETURN_LONG(nbytes);
3285 : }
3286 : /* }}} */
3287 :
3288 : /* {{{ proto int pg_lo_read_all(resource large_object)
3289 : Read a large object and send straight to browser */
3290 : PHP_FUNCTION(pg_lo_read_all)
3291 1 : {
3292 : zval *pgsql_id;
3293 : int tbytes;
3294 : volatile int nbytes;
3295 : char buf[PGSQL_LO_READ_BUF_SIZE];
3296 : pgLofp *pgsql;
3297 :
3298 1 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pgsql_id) == FAILURE) {
3299 0 : return;
3300 : }
3301 :
3302 1 : ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_id, -1, "PostgreSQL large object", le_lofp);
3303 :
3304 1 : tbytes = 0;
3305 3 : while ((nbytes = lo_read((PGconn *)pgsql->conn, pgsql->lofd, buf, PGSQL_LO_READ_BUF_SIZE))>0) {
3306 1 : php_body_write(buf, nbytes TSRMLS_CC);
3307 1 : tbytes += nbytes;
3308 : }
3309 1 : RETURN_LONG(tbytes);
3310 : }
3311 : /* }}} */
3312 :
3313 : /* {{{ proto int pg_lo_import([resource connection, ] string filename [, mixed oid])
3314 : Import large object direct from filesystem */
3315 : PHP_FUNCTION(pg_lo_import)
3316 1 : {
3317 1 : zval *pgsql_link = NULL, *oid = NULL;
3318 : char *file_in;
3319 1 : int id = -1, name_len;
3320 1 : int argc = ZEND_NUM_ARGS();
3321 : PGconn *pgsql;
3322 : Oid returned_oid;
3323 :
3324 1 : if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3325 : "rs|z", &pgsql_link, &file_in, &name_len, &oid) == SUCCESS) {
3326 : ;
3327 : }
3328 0 : else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3329 : "s|z", &file_in, &name_len, &oid) == SUCCESS) {
3330 0 : id = PGG(default_link);
3331 0 : CHECK_DEFAULT_LINK(id);
3332 : }
3333 : /* old calling convention, deprecated since PHP 4.2 */
3334 0 : else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3335 : "sr", &file_in, &name_len, &pgsql_link ) == SUCCESS) {
3336 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Old API is used");
3337 : }
3338 : else {
3339 0 : WRONG_PARAM_COUNT;
3340 : }
3341 :
3342 1 : if (PG(safe_mode) &&(!php_checkuid(file_in, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
3343 0 : RETURN_FALSE;
3344 : }
3345 :
3346 1 : if (php_check_open_basedir(file_in TSRMLS_CC)) {
3347 0 : RETURN_FALSE;
3348 : }
3349 :
3350 1 : if (pgsql_link == NULL && id == -1) {
3351 0 : RETURN_FALSE;
3352 : }
3353 :
3354 1 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3355 :
3356 1 : if (oid) {
3357 : #ifndef HAVE_PG_LO_IMPORT_WITH_OID
3358 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "OID value passing not supported");
3359 : #else
3360 : Oid wanted_oid;
3361 : switch (Z_TYPE_P(oid)) {
3362 : case IS_STRING:
3363 : {
3364 : char *end_ptr;
3365 : wanted_oid = (Oid)strtoul(Z_STRVAL_P(oid), &end_ptr, 10);
3366 : if ((Z_STRVAL_P(oid)+Z_STRLEN_P(oid)) != end_ptr) {
3367 : /* wrong integer format */
3368 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
3369 : RETURN_FALSE;
3370 : }
3371 : }
3372 : break;
3373 : case IS_LONG:
3374 : if (Z_LVAL_P(oid) < (long)InvalidOid) {
3375 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
3376 : RETURN_FALSE;
3377 : }
3378 : wanted_oid = (Oid)Z_LVAL_P(oid);
3379 : break;
3380 : default:
3381 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
3382 : RETURN_FALSE;
3383 : }
3384 :
3385 : returned_oid = lo_import_with_oid(pgsql, file_in, wanted_oid);
3386 :
3387 : if (returned_oid == InvalidOid) {
3388 : RETURN_FALSE;
3389 : }
3390 :
3391 : PGSQL_RETURN_OID(returned_oid);
3392 : #endif
3393 : }
3394 :
3395 1 : returned_oid = lo_import(pgsql, file_in);
3396 :
3397 1 : if (returned_oid == InvalidOid) {
3398 0 : RETURN_FALSE;
3399 : }
3400 1 : PGSQL_RETURN_OID(returned_oid);
3401 : }
3402 : /* }}} */
3403 :
3404 : /* {{{ proto bool pg_lo_export([resource connection, ] int objoid, string filename)
3405 : Export large object direct to filesystem */
3406 : PHP_FUNCTION(pg_lo_export)
3407 1 : {
3408 1 : zval *pgsql_link = NULL;
3409 : char *file_out, *oid_string, *end_ptr;
3410 : int oid_strlen;
3411 1 : int id = -1, name_len;
3412 : long oid_long;
3413 : Oid oid;
3414 : PGconn *pgsql;
3415 1 : int argc = ZEND_NUM_ARGS();
3416 :
3417 : /* allow string to handle large OID value correctly */
3418 1 : if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3419 : "rls", &pgsql_link, &oid_long, &file_out, &name_len) == SUCCESS) {
3420 0 : if (oid_long <= InvalidOid) {
3421 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
3422 0 : RETURN_FALSE;
3423 : }
3424 0 : oid = (Oid)oid_long;
3425 : }
3426 1 : else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3427 : "rss", &pgsql_link, &oid_string, &oid_strlen, &file_out, &name_len) == SUCCESS) {
3428 0 : oid = (Oid)strtoul(oid_string, &end_ptr, 10);
3429 0 : if ((oid_string+oid_strlen) != end_ptr) {
3430 : /* wrong integer format */
3431 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
3432 0 : RETURN_FALSE;
3433 : }
3434 : }
3435 1 : else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3436 : "ls", &oid_long, &file_out, &name_len) == SUCCESS) {
3437 0 : if (oid_long <= InvalidOid) {
3438 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
3439 0 : RETURN_FALSE;
3440 : }
3441 0 : oid = (Oid)oid_long;
3442 0 : id = PGG(default_link);
3443 0 : CHECK_DEFAULT_LINK(id);
3444 : }
3445 1 : else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3446 : "ss", &oid_string, &oid_strlen, &file_out, &name_len) == SUCCESS) {
3447 0 : oid = (Oid)strtoul(oid_string, &end_ptr, 10);
3448 0 : if ((oid_string+oid_strlen) != end_ptr) {
3449 : /* wrong integer format */
3450 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
3451 0 : RETURN_FALSE;
3452 : }
3453 0 : id = PGG(default_link);
3454 0 : CHECK_DEFAULT_LINK(id);
3455 : }
3456 1 : else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3457 : "ssr", &oid_string, &oid_strlen, &file_out, &name_len, &pgsql_link) == SUCCESS) {
3458 1 : oid = (Oid)strtoul(oid_string, &end_ptr, 10);
3459 1 : if ((oid_string+oid_strlen) != end_ptr) {
3460 : /* wrong integer format */
3461 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
3462 0 : RETURN_FALSE;
3463 : }
3464 : }
3465 0 : else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3466 : "lsr", &oid_long, &file_out, &name_len, &pgsql_link) == SUCCESS) {
3467 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Old API is used");
3468 0 : if (oid_long <= InvalidOid) {
3469 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
3470 0 : RETURN_FALSE;
3471 : }
3472 0 : oid = (Oid)oid_long;
3473 : }
3474 : else {
3475 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Requires 2 or 3 arguments");
3476 0 : RETURN_FALSE;
3477 : }
3478 :
3479 1 : if (PG(safe_mode) &&(!php_checkuid(file_out, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
3480 0 : RETURN_FALSE;
3481 : }
3482 :
3483 1 : if (php_check_open_basedir(file_out TSRMLS_CC)) {
3484 0 : RETURN_FALSE;
3485 : }
3486 :
3487 1 : if (pgsql_link == NULL && id == -1) {
3488 0 : RETURN_FALSE;
3489 : }
3490 :
3491 1 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3492 :
3493 1 : if (lo_export(pgsql, oid, file_out)) {
3494 1 : RETURN_TRUE;
3495 : }
3496 0 : RETURN_FALSE;
3497 : }
3498 : /* }}} */
3499 :
3500 : /* {{{ proto bool pg_lo_seek(resource large_object, int offset [, int whence])
3501 : Seeks position of large object */
3502 : PHP_FUNCTION(pg_lo_seek)
3503 1 : {
3504 1 : zval *pgsql_id = NULL;
3505 1 : long offset = 0, whence = SEEK_CUR;
3506 : pgLofp *pgsql;
3507 1 : int argc = ZEND_NUM_ARGS();
3508 :
3509 1 : if (zend_parse_parameters(argc TSRMLS_CC, "rl|l", &pgsql_id, &offset, &whence) == FAILURE) {
3510 0 : return;
3511 : }
3512 1 : if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) {
3513 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid whence parameter");
3514 0 : return;
3515 : }
3516 :
3517 1 : ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_id, -1, "PostgreSQL large object", le_lofp);
3518 :
3519 1 : if (lo_lseek((PGconn *)pgsql->conn, pgsql->lofd, offset, whence) > -1) {
3520 1 : RETURN_TRUE;
3521 : } else {
3522 0 : RETURN_FALSE;
3523 : }
3524 : }
3525 : /* }}} */
3526 :
3527 : /* {{{ proto int pg_lo_tell(resource large_object)
3528 : Returns current position of large object */
3529 : PHP_FUNCTION(pg_lo_tell)
3530 1 : {
3531 1 : zval *pgsql_id = NULL;
3532 1 : int offset = 0;
3533 : pgLofp *pgsql;
3534 1 : int argc = ZEND_NUM_ARGS();
3535 :
3536 1 : if (zend_parse_parameters(argc TSRMLS_CC, "r", &pgsql_id) == FAILURE) {
3537 0 : return;
3538 : }
3539 :
3540 1 : ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_id, -1, "PostgreSQL large object", le_lofp);
3541 :
3542 1 : offset = lo_tell((PGconn *)pgsql->conn, pgsql->lofd);
3543 1 : RETURN_LONG(offset);
3544 : }
3545 : /* }}} */
3546 :
3547 : #if HAVE_PQSETERRORVERBOSITY
3548 : /* {{{ proto int pg_set_error_verbosity([resource connection,] int verbosity)
3549 : Set error verbosity */
3550 : PHP_FUNCTION(pg_set_error_verbosity)
3551 3 : {
3552 3 : zval *pgsql_link = NULL;
3553 : long verbosity;
3554 3 : int id = -1, argc = ZEND_NUM_ARGS();
3555 : PGconn *pgsql;
3556 :
3557 3 : if (argc == 1) {
3558 3 : if (zend_parse_parameters(argc TSRMLS_CC, "l", &verbosity) == FAILURE) {
3559 0 : return;
3560 : }
3561 3 : id = PGG(default_link);
3562 3 : CHECK_DEFAULT_LINK(id);
3563 : } else {
3564 0 : if (zend_parse_parameters(argc TSRMLS_CC, "rl", &pgsql_link, &verbosity) == FAILURE) {
3565 0 : return;
3566 : }
3567 : }
3568 :
3569 3 : if (pgsql_link == NULL && id == -1) {
3570 0 : RETURN_FALSE;
3571 : }
3572 :
3573 3 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3574 :
3575 3 : if (verbosity & (PQERRORS_TERSE|PQERRORS_DEFAULT|PQERRORS_VERBOSE)) {
3576 2 : Z_LVAL_P(return_value) = PQsetErrorVerbosity(pgsql, verbosity);
3577 2 : Z_TYPE_P(return_value) = IS_LONG;
3578 : } else {
3579 1 : RETURN_FALSE;
3580 : }
3581 : }
3582 : /* }}} */
3583 : #endif
3584 :
3585 : #ifdef HAVE_PQCLIENTENCODING
3586 : /* {{{ proto int pg_set_client_encoding([resource connection,] string encoding)
3587 : Set client encoding */
3588 : PHP_FUNCTION(pg_set_client_encoding)
3589 1 : {
3590 : char *encoding;
3591 : int encoding_len;
3592 1 : zval *pgsql_link = NULL;
3593 1 : int id = -1, argc = ZEND_NUM_ARGS();
3594 : PGconn *pgsql;
3595 :
3596 1 : if (argc == 1) {
3597 0 : if (zend_parse_parameters(argc TSRMLS_CC, "s", &encoding, &encoding_len) == FAILURE) {
3598 0 : return;
3599 : }
3600 0 : id = PGG(default_link);
3601 0 : CHECK_DEFAULT_LINK(id);
3602 : } else {
3603 1 : if (zend_parse_parameters(argc TSRMLS_CC, "rs", &pgsql_link, &encoding, &encoding_len) == FAILURE) {
3604 0 : return;
3605 : }
3606 : }
3607 :
3608 1 : if (pgsql_link == NULL && id == -1) {
3609 0 : RETURN_FALSE;
3610 : }
3611 :
3612 1 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3613 :
3614 1 : Z_LVAL_P(return_value) = PQsetClientEncoding(pgsql, encoding);
3615 1 : Z_TYPE_P(return_value) = IS_LONG;
3616 : }
3617 : /* }}} */
3618 :
3619 : /* {{{ proto string pg_client_encoding([resource connection])
3620 : Get the current client encoding */
3621 : PHP_FUNCTION(pg_client_encoding)
3622 1 : {
3623 1 : zval *pgsql_link = NULL;
3624 1 : int id = -1, argc = ZEND_NUM_ARGS();
3625 : PGconn *pgsql;
3626 :
3627 1 : if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) {
3628 0 : return;
3629 : }
3630 :
3631 1 : if (argc == 0) {
3632 0 : id = PGG(default_link);
3633 0 : CHECK_DEFAULT_LINK(id);
3634 : }
3635 :
3636 1 : if (pgsql_link == NULL && id == -1) {
3637 0 : RETURN_FALSE;
3638 : }
3639 :
3640 1 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3641 :
3642 : /* Just do the same as found in PostgreSQL sources... */
3643 :
3644 : #ifndef HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT
3645 : #define pg_encoding_to_char(x) "SQL_ASCII"
3646 : #endif
3647 :
3648 1 : Z_STRVAL_P(return_value) = (char *) pg_encoding_to_char(PQclientEncoding(pgsql));
3649 1 : Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
3650 1 : Z_STRVAL_P(return_value) = (char *) estrdup(Z_STRVAL_P(return_value));
3651 1 : Z_TYPE_P(return_value) = IS_STRING;
3652 : }
3653 : /* }}} */
3654 : #endif
3655 :
3656 : #if !HAVE_PQGETCOPYDATA
3657 : #define COPYBUFSIZ 8192
3658 : #endif
3659 :
3660 : /* {{{ proto bool pg_end_copy([resource connection])
3661 : Sync with backend. Completes the Copy command */
3662 : PHP_FUNCTION(pg_end_copy)
3663 0 : {
3664 0 : zval *pgsql_link = NULL;
3665 0 : int id = -1, argc = ZEND_NUM_ARGS();
3666 : PGconn *pgsql;
3667 0 : int result = 0;
3668 :
3669 0 : if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) {
3670 0 : return;
3671 : }
3672 :
3673 0 : if (argc == 0) {
3674 0 : id = PGG(default_link);
3675 0 : CHECK_DEFAULT_LINK(id);
3676 : }
3677 :
3678 0 : if (pgsql_link == NULL && id == -1) {
3679 0 : RETURN_FALSE;
3680 : }
3681 :
3682 0 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3683 :
3684 0 : result = PQendcopy(pgsql);
3685 :
3686 0 : if (result!=0) {
3687 0 : PHP_PQ_ERROR("Query failed: %s", pgsql);
3688 0 : RETURN_FALSE;
3689 : }
3690 0 : RETURN_TRUE;
3691 : }
3692 : /* }}} */
3693 :
3694 :
3695 : /* {{{ proto bool pg_put_line([resource connection,] string query)
3696 : Send null-terminated string to backend server*/
3697 : PHP_FUNCTION(pg_put_line)
3698 0 : {
3699 : char *query;
3700 0 : zval *pgsql_link = NULL;
3701 0 : int query_len, id = -1;
3702 : PGconn *pgsql;
3703 0 : int result = 0, argc = ZEND_NUM_ARGS();
3704 :
3705 0 : if (argc == 1) {
3706 0 : if (zend_parse_parameters(argc TSRMLS_CC, "s", &query, &query_len) == FAILURE) {
3707 0 : return;
3708 : }
3709 0 : id = PGG(default_link);
3710 0 : CHECK_DEFAULT_LINK(id);
3711 : } else {
3712 0 : if (zend_parse_parameters(argc TSRMLS_CC, "rs", &pgsql_link, &query, &query_len) == FAILURE) {
3713 0 : return;
3714 : }
3715 : }
3716 :
3717 0 : if (pgsql_link == NULL && id == -1) {
3718 0 : RETURN_FALSE;
3719 : }
3720 :
3721 0 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3722 :
3723 0 : result = PQputline(pgsql, query);
3724 0 : if (result==EOF) {
3725 0 : PHP_PQ_ERROR("Query failed: %s", pgsql);
3726 0 : RETURN_FALSE;
3727 : }
3728 0 : RETURN_TRUE;
3729 : }
3730 : /* }}} */
3731 :
3732 : /* {{{ proto array pg_copy_to(resource connection, string table_name [, string delimiter [, string null_as]])
3733 : Copy table to array */
3734 : PHP_FUNCTION(pg_copy_to)
3735 1 : {
3736 : zval *pgsql_link;
3737 1 : char *table_name, *pg_delim = NULL, *pg_null_as = NULL;
3738 : int table_name_len, pg_delim_len, pg_null_as_len;
3739 : char *query;
3740 1 : int id = -1;
3741 : PGconn *pgsql;
3742 : PGresult *pgsql_result;
3743 : ExecStatusType status;
3744 1 : int copydone = 0;
3745 : #if !HAVE_PQGETCOPYDATA
3746 : char copybuf[COPYBUFSIZ];
3747 : #endif
3748 1 : char *csv = (char *)NULL;
3749 : int ret;
3750 1 : int argc = ZEND_NUM_ARGS();
3751 :
3752 1 : if (zend_parse_parameters(argc TSRMLS_CC, "rs|ss",
3753 : &pgsql_link, &table_name, &table_name_len,
3754 : &pg_delim, &pg_delim_len, &pg_null_as, &pg_null_as_len) == FAILURE) {
3755 0 : return;
3756 : }
3757 1 : if (!pg_delim) {
3758 1 : pg_delim = "\t";
3759 : }
3760 :
3761 1 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3762 :
3763 1 : if (!pg_null_as) {
3764 1 : pg_null_as = safe_estrdup("\\\\N");
3765 : }
3766 :
3767 1 : spprintf(&query, 0, "COPY \"%s\" TO STDOUT DELIMITERS '%c' WITH NULL AS '%s'", table_name, *pg_delim, pg_null_as);
3768 :
3769 2 : while ((pgsql_result = PQgetResult(pgsql))) {
3770 0 : PQclear(pgsql_result);
3771 : }
3772 1 : pgsql_result = PQexec(pgsql, query);
3773 1 : efree(pg_null_as);
3774 1 : efree(query);
3775 :
3776 1 : if (pgsql_result) {
3777 1 : status = PQresultStatus(pgsql_result);
3778 : } else {
3779 0 : status = (ExecStatusType) PQstatus(pgsql);
3780 : }
3781 :
3782 1 : switch (status) {
3783 : case PGRES_COPY_OUT:
3784 1 : if (pgsql_result) {
3785 1 : PQclear(pgsql_result);
3786 1 : array_init(return_value);
3787 : #if HAVE_PQGETCOPYDATA
3788 1005 : while (!copydone)
3789 : {
3790 1003 : ret = PQgetCopyData(pgsql, &csv, 0);
3791 1003 : switch (ret) {
3792 : case -1:
3793 1 : copydone = 1;
3794 1 : break;
3795 : case 0:
3796 : case -2:
3797 0 : PHP_PQ_ERROR("getline failed: %s", pgsql);
3798 0 : RETURN_FALSE;
3799 : break;
3800 : default:
3801 1002 : add_next_index_string(return_value, csv, 1);
3802 1002 : PQfreemem(csv);
3803 : break;
3804 : }
3805 : }
3806 : #else
3807 : while (!copydone)
3808 : {
3809 : if ((ret = PQgetline(pgsql, copybuf, COPYBUFSIZ))) {
3810 : PHP_PQ_ERROR("getline failed: %s", pgsql);
3811 : RETURN_FALSE;
3812 : }
3813 :
3814 : if (copybuf[0] == '\\' &&
3815 : copybuf[1] == '.' &&
3816 : copybuf[2] == '\0')
3817 : {
3818 : copydone = 1;
3819 : }
3820 : else
3821 : {
3822 : if (csv == (char *)NULL) {
3823 : csv = estrdup(copybuf);
3824 : } else {
3825 : csv = (char *)erealloc(csv, strlen(csv) + sizeof(char)*(COPYBUFSIZ+1));
3826 : strcat(csv, copybuf);
3827 : }
3828 :
3829 : switch (ret)
3830 : {
3831 : case EOF:
3832 : copydone = 1;
3833 : case 0:
3834 : add_next_index_string(return_value, csv, 1);
3835 : efree(csv);
3836 : csv = (char *)NULL;
3837 : break;
3838 : case 1:
3839 : break;
3840 : }
3841 : }
3842 : }
3843 : if (PQendcopy(pgsql)) {
3844 : PHP_PQ_ERROR("endcopy failed: %s", pgsql);
3845 : RETURN_FALSE;
3846 : }
3847 : #endif
3848 3 : while ((pgsql_result = PQgetResult(pgsql))) {
3849 1 : PQclear(pgsql_result);
3850 : }
3851 : } else {
3852 0 : PQclear(pgsql_result);
3853 0 : RETURN_FALSE;
3854 : }
3855 1 : break;
3856 : default:
3857 0 : PQclear(pgsql_result);
3858 0 : PHP_PQ_ERROR("Copy command failed: %s", pgsql);
3859 0 : RETURN_FALSE;
3860 : break;
3861 : }
3862 : }
3863 : /* }}} */
3864 :
3865 : /* {{{ proto bool pg_copy_from(resource connection, string table_name , array rows [, string delimiter [, string null_as]])
3866 : Copy table from array */
3867 : PHP_FUNCTION(pg_copy_from)
3868 1 : {
3869 1 : zval *pgsql_link = NULL, *pg_rows;
3870 : zval **tmp;
3871 1 : char *table_name, *pg_delim = NULL, *pg_null_as = NULL;
3872 : int table_name_len, pg_delim_len, pg_null_as_len;
3873 1 : int pg_null_as_free = 0;
3874 : char *query;
3875 : HashPosition pos;
3876 1 : int id = -1;
3877 : PGconn *pgsql;
3878 : PGresult *pgsql_result;
3879 : ExecStatusType status;
3880 1 : int argc = ZEND_NUM_ARGS();
3881 :
3882 1 : if (zend_parse_parameters(argc TSRMLS_CC, "rsa|ss",
3883 : &pgsql_link, &table_name, &table_name_len, &pg_rows,
3884 : &pg_delim, &pg_delim_len, &pg_null_as, &pg_null_as_len) == FAILURE) {
3885 0 : return;
3886 : }
3887 1 : if (!pg_delim) {
3888 1 : pg_delim = "\t";
3889 : }
3890 1 : if (!pg_null_as) {
3891 1 : pg_null_as = safe_estrdup("\\\\N");
3892 1 : pg_null_as_free = 1;
3893 : }
3894 :
3895 1 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3896 :
3897 1 : spprintf(&query, 0, "COPY \"%s\" FROM STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, *pg_delim, pg_null_as);
3898 2 : while ((pgsql_result = PQgetResult(pgsql))) {
3899 0 : PQclear(pgsql_result);
3900 : }
3901 1 : pgsql_result = PQexec(pgsql, query);
3902 :
3903 1 : if (pg_null_as_free) {
3904 1 : efree(pg_null_as);
3905 : }
3906 1 : efree(query);
3907 :
3908 1 : if (pgsql_result) {
3909 1 : status = PQresultStatus(pgsql_result);
3910 : } else {
3911 0 : status = (ExecStatusType) PQstatus(pgsql);
3912 : }
3913 :
3914 1 : switch (status) {
3915 : case PGRES_COPY_IN:
3916 1 : if (pgsql_result) {
3917 1 : int command_failed = 0;
3918 1 : PQclear(pgsql_result);
3919 1 : zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(pg_rows), &pos);
3920 : #if HAVE_PQPUTCOPYDATA
3921 1004 : while (zend_hash_get_current_data_ex(Z_ARRVAL_P(pg_rows), (void **) &tmp, &pos) == SUCCESS) {
3922 1002 : convert_to_string_ex(tmp);
3923 1002 : query = (char *)emalloc(Z_STRLEN_PP(tmp) + 2);
3924 1002 : strlcpy(query, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp) + 2);
3925 1002 : if(Z_STRLEN_PP(tmp) > 0 && *(query + Z_STRLEN_PP(tmp) - 1) != '\n') {
3926 0 : strlcat(query, "\n", Z_STRLEN_PP(tmp) + 2);
3927 : }
3928 1002 : if (PQputCopyData(pgsql, query, strlen(query)) != 1) {
3929 0 : efree(query);
3930 0 : PHP_PQ_ERROR("copy failed: %s", pgsql);
3931 0 : RETURN_FALSE;
3932 : }
3933 1002 : efree(query);
3934 1002 : zend_hash_move_forward_ex(Z_ARRVAL_P(pg_rows), &pos);
3935 : }
3936 1 : if (PQputCopyEnd(pgsql, NULL) != 1) {
3937 0 : PHP_PQ_ERROR("putcopyend failed: %s", pgsql);
3938 0 : RETURN_FALSE;
3939 : }
3940 : #else
3941 : while (zend_hash_get_current_data_ex(Z_ARRVAL_P(pg_rows), (void **) &tmp, &pos) == SUCCESS) {
3942 : convert_to_string_ex(tmp);
3943 : query = (char *)emalloc(Z_STRLEN_PP(tmp) + 2);
3944 : strlcpy(query, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp) + 2);
3945 : if(Z_STRLEN_PP(tmp) > 0 && *(query + Z_STRLEN_PP(tmp) - 1) != '\n') {
3946 : strlcat(query, "\n", Z_STRLEN_PP(tmp) + 2);
3947 : }
3948 : if (PQputline(pgsql, query)==EOF) {
3949 : efree(query);
3950 : PHP_PQ_ERROR("copy failed: %s", pgsql);
3951 : RETURN_FALSE;
3952 : }
3953 : efree(query);
3954 : zend_hash_move_forward_ex(Z_ARRVAL_P(pg_rows), &pos);
3955 : }
3956 : if (PQputline(pgsql, "\\.\n") == EOF) {
3957 : PHP_PQ_ERROR("putline failed: %s", pgsql);
3958 : RETURN_FALSE;
3959 : }
3960 : if (PQendcopy(pgsql)) {
3961 : PHP_PQ_ERROR("endcopy failed: %s", pgsql);
3962 : RETURN_FALSE;
3963 : }
3964 : #endif
3965 3 : while ((pgsql_result = PQgetResult(pgsql))) {
3966 1 : if (PGRES_COMMAND_OK != PQresultStatus(pgsql_result)) {
3967 0 : PHP_PQ_ERROR("Copy command failed: %s", pgsql);
3968 0 : command_failed = 1;
3969 : }
3970 1 : PQclear(pgsql_result);
3971 : }
3972 1 : if (command_failed) {
3973 0 : RETURN_FALSE;
3974 : }
3975 : } else {
3976 0 : PQclear(pgsql_result);
3977 0 : RETURN_FALSE;
3978 : }
3979 1 : RETURN_TRUE;
3980 : break;
3981 : default:
3982 0 : PQclear(pgsql_result);
3983 0 : PHP_PQ_ERROR("Copy command failed: %s", pgsql);
3984 0 : RETURN_FALSE;
3985 : break;
3986 : }
3987 : }
3988 : /* }}} */
3989 :
3990 : #ifdef HAVE_PQESCAPE
3991 : /* {{{ proto string pg_escape_string([resource connection,] string data)
3992 : Escape string for text/char type */
3993 : PHP_FUNCTION(pg_escape_string)
3994 1 : {
3995 1 : char *from = NULL, *to = NULL;
3996 : zval *pgsql_link;
3997 : #ifdef HAVE_PQESCAPE_CONN
3998 : PGconn *pgsql;
3999 : #endif
4000 : int to_len;
4001 : int from_len;
4002 1 : int id = -1;
4003 :
4004 1 : switch (ZEND_NUM_ARGS()) {
4005 : case 1:
4006 1 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &from, &from_len) == FAILURE) {
4007 0 : return;
4008 : }
4009 1 : pgsql_link = NULL;
4010 1 : id = PGG(default_link);
4011 1 : break;
4012 :
4013 : default:
4014 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pgsql_link, &from, &from_len) == FAILURE) {
4015 0 : return;
4016 : }
4017 : break;
4018 : }
4019 :
4020 1 : to = (char *) safe_emalloc(from_len, 2, 1);
4021 :
4022 : #ifdef HAVE_PQESCAPE_CONN
4023 1 : if (pgsql_link != NULL || id != -1) {
4024 0 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4025 0 : to_len = (int) PQescapeStringConn(pgsql, to, from, (size_t)from_len, NULL);
4026 : } else
4027 : #endif
4028 1 : to_len = (int) PQescapeString(to, from, (size_t)from_len);
4029 :
4030 1 : RETURN_STRINGL(to, to_len, 0);
4031 : }
4032 : /* }}} */
4033 :
4034 : /* {{{ proto string pg_escape_bytea([resource connection,] string data)
4035 : Escape binary for bytea type */
4036 : PHP_FUNCTION(pg_escape_bytea)
4037 3 : {
4038 3 : char *from = NULL, *to = NULL;
4039 : size_t to_len;
4040 3 : int from_len, id = -1;
4041 : #ifdef HAVE_PQESCAPE_BYTEA_CONN
4042 : PGconn *pgsql;
4043 : #endif
4044 : zval *pgsql_link;
4045 :
4046 3 : switch (ZEND_NUM_ARGS()) {
4047 : case 1:
4048 3 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &from, &from_len) == FAILURE) {
4049 0 : return;
4050 : }
4051 3 : pgsql_link = NULL;
4052 3 : id = PGG(default_link);
4053 3 : break;
4054 :
4055 : default:
4056 0 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pgsql_link, &from, &from_len) == FAILURE) {
4057 0 : return;
4058 : }
4059 : break;
4060 : }
4061 :
4062 : #ifdef HAVE_PQESCAPE_BYTEA_CONN
4063 4 : if (pgsql_link != NULL || id != -1) {
4064 1 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4065 1 : to = (char *)PQescapeByteaConn(pgsql, from, (size_t)from_len, &to_len);
4066 : } else
4067 : #endif
4068 2 : to = (char *)PQescapeBytea((unsigned char*)from, from_len, &to_len);
4069 :
4070 3 : RETVAL_STRINGL(to, to_len-1, 1); /* to_len includes addtional '\0' */
4071 3 : PQfreemem(to);
4072 : }
4073 : /* }}} */
4074 :
4075 : #if !HAVE_PQUNESCAPEBYTEA
4076 : /* PQunescapeBytea() from PostgreSQL 7.3 to provide bytea unescape feature to 7.2 users.
4077 : Renamed to php_pgsql_unescape_bytea() */
4078 : /*
4079 : * PQunescapeBytea - converts the null terminated string representation
4080 : * of a bytea, strtext, into binary, filling a buffer. It returns a
4081 : * pointer to the buffer which is NULL on error, and the size of the
4082 : * buffer in retbuflen. The pointer may subsequently be used as an
4083 : * argument to the function free(3). It is the reverse of PQescapeBytea.
4084 : *
4085 : * The following transformations are reversed:
4086 : * '\0' == ASCII 0 == \000
4087 : * '\'' == ASCII 39 == \'
4088 : * '\\' == ASCII 92 == \\
4089 : *
4090 : * States:
4091 : * 0 normal 0->1->2->3->4
4092 : * 1 \ 1->5
4093 : * 2 \0 1->6
4094 : * 3 \00
4095 : * 4 \000
4096 : * 5 \'
4097 : * 6 \\
4098 : */
4099 : static unsigned char * php_pgsql_unescape_bytea(unsigned char *strtext, size_t *retbuflen)
4100 : {
4101 : size_t buflen;
4102 : unsigned char *buffer,
4103 : *sp,
4104 : *bp;
4105 : unsigned int state = 0;
4106 :
4107 : if (strtext == NULL)
4108 : return NULL;
4109 : buflen = strlen(strtext); /* will shrink, also we discover if
4110 : * strtext */
4111 : buffer = (unsigned char *) emalloc(buflen); /* isn't NULL terminated */
4112 : for (bp = buffer, sp = strtext; *sp != '\0'; bp++, sp++)
4113 : {
4114 : switch (state)
4115 : {
4116 : case 0:
4117 : if (*sp == '\\')
4118 : state = 1;
4119 : *bp = *sp;
4120 : break;
4121 : case 1:
4122 : if (*sp == '\'') /* state=5 */
4123 : { /* replace \' with 39 */
4124 : bp--;
4125 : *bp = '\'';
4126 : buflen--;
4127 : state = 0;
4128 : }
4129 : else if (*sp == '\\') /* state=6 */
4130 : { /* replace \\ with 92 */
4131 : bp--;
4132 : *bp = '\\';
4133 : buflen--;
4134 : state = 0;
4135 : }
4136 : else
4137 : {
4138 : if (isdigit(*sp))
4139 : state = 2;
4140 : else
4141 : state = 0;
4142 : *bp = *sp;
4143 : }
4144 : break;
4145 : case 2:
4146 : if (isdigit(*sp))
4147 : state = 3;
4148 : else
4149 : state = 0;
4150 : *bp = *sp;
4151 : break;
4152 : case 3:
4153 : if (isdigit(*sp)) /* state=4 */
4154 : {
4155 : unsigned char *start, *end, buf[4]; /* 000 + '\0' */
4156 :
4157 : bp -= 3;
4158 : memcpy(buf, sp-2, 3);
4159 : buf[3] = '\0';
4160 : start = buf;
4161 : *bp = (unsigned char)strtoul(start, (char **)&end, 8);
4162 : buflen -= 3;
4163 : state = 0;
4164 : }
4165 : else
4166 : {
4167 : *bp = *sp;
4168 : state = 0;
4169 : }
4170 : break;
4171 : }
4172 : }
4173 : buffer = erealloc(buffer, buflen+1);
4174 : buffer[buflen] = '\0';
4175 :
4176 : *retbuflen = buflen;
4177 : return buffer;
4178 : }
4179 : #endif
4180 :
4181 : /* {{{ proto string pg_unescape_bytea(string data)
4182 : Unescape binary for bytea type */
4183 : PHP_FUNCTION(pg_unescape_bytea)
4184 3 : {
4185 3 : char *from = NULL, *to = NULL, *tmp = NULL;
4186 : size_t to_len;
4187 : int from_len;
4188 3 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
4189 : &from, &from_len) == FAILURE) {
4190 0 : return;
4191 : }
4192 :
4193 : #if HAVE_PQUNESCAPEBYTEA
4194 3 : tmp = (char *)PQunescapeBytea((unsigned char*)from, &to_len);
4195 3 : to = estrndup(tmp, to_len);
4196 3 : PQfreemem(tmp);
4197 : #else
4198 : to = (char *)php_pgsql_unescape_bytea((unsigned char*)from, &to_len);
4199 : #endif
4200 3 : if (!to) {
4201 0 : RETURN_FALSE;
4202 : }
4203 3 : RETVAL_STRINGL(to, to_len, 0);
4204 : }
4205 : /* }}} */
4206 : #endif
4207 :
4208 : /* {{{ proto string pg_result_error(resource result)
4209 : Get error message associated with result */
4210 : PHP_FUNCTION(pg_result_error)
4211 5 : {
4212 : zval *result;
4213 : PGresult *pgsql_result;
4214 : pgsql_result_handle *pg_result;
4215 5 : char *err = NULL;
4216 :
4217 5 : if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
4218 : &result) == FAILURE) {
4219 0 : RETURN_FALSE;
4220 : }
4221 :
4222 5 : ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
4223 :
4224 5 : pgsql_result = pg_result->result;
4225 5 : if (!pgsql_result) {
4226 0 : RETURN_FALSE;
4227 : }
4228 5 : err = (char *)PQresultErrorMessage(pgsql_result);
4229 5 : RETURN_STRING(err,1);
4230 : }
4231 : /* }}} */
4232 :
4233 : #if HAVE_PQRESULTERRORFIELD
4234 : /* {{{ proto string pg_result_error_field(resource result, int fieldcode)
4235 : Get error message field associated with result */
4236 : PHP_FUNCTION(pg_result_error_field)
4237 12 : {
4238 : zval *result;
4239 : long fieldcode;
4240 : PGresult *pgsql_result;
4241 : pgsql_result_handle *pg_result;
4242 12 : char *field = NULL;
4243 :
4244 12 : if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "rl",
4245 : &result, &fieldcode) == FAILURE) {
4246 0 : RETURN_FALSE;
4247 : }
4248 :
4249 12 : ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
4250 :
4251 12 : pgsql_result = pg_result->result;
4252 12 : if (!pgsql_result) {
4253 0 : RETURN_FALSE;
4254 : }
4255 12 : if (fieldcode & (PG_DIAG_SEVERITY|PG_DIAG_SQLSTATE|PG_DIAG_MESSAGE_PRIMARY|PG_DIAG_MESSAGE_DETAIL
4256 : |PG_DIAG_MESSAGE_HINT|PG_DIAG_STATEMENT_POSITION
4257 : #if PG_DIAG_INTERNAL_POSITION
4258 : |PG_DIAG_INTERNAL_POSITION
4259 : #endif
4260 : #if PG_DIAG_INTERNAL_QUERY
4261 : |PG_DIAG_INTERNAL_QUERY
4262 : #endif
4263 : |PG_DIAG_CONTEXT|PG_DIAG_SOURCE_FILE|PG_DIAG_SOURCE_LINE
4264 : |PG_DIAG_SOURCE_FUNCTION)) {
4265 12 : field = (char *)PQresultErrorField(pgsql_result, fieldcode);
4266 12 : if (field == NULL) {
4267 12 : RETURN_NULL();
4268 : } else {
4269 0 : RETURN_STRING(field, 1);
4270 : }
4271 : } else {
4272 0 : RETURN_FALSE;
4273 : }
4274 : }
4275 : /* }}} */
4276 : #endif
4277 :
4278 : /* {{{ proto int pg_connection_status(resource connnection)
4279 : Get connection status */
4280 : PHP_FUNCTION(pg_connection_status)
4281 7 : {
4282 7 : zval *pgsql_link = NULL;
4283 7 : int id = -1;
4284 : PGconn *pgsql;
4285 :
4286 7 : if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
4287 : &pgsql_link) == FAILURE) {
4288 0 : RETURN_FALSE;
4289 : }
4290 :
4291 7 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4292 :
4293 7 : RETURN_LONG(PQstatus(pgsql));
4294 : }
4295 :
4296 : /* }}} */
4297 :
4298 : #if HAVE_PGTRANSACTIONSTATUS
4299 : /* {{{ proto int pg_transaction_status(resource connnection)
4300 : Get transaction status */
4301 : PHP_FUNCTION(pg_transaction_status)
4302 1 : {
4303 1 : zval *pgsql_link = NULL;
4304 1 : int id = -1;
4305 : PGconn *pgsql;
4306 :
4307 1 : if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
4308 : &pgsql_link) == FAILURE) {
4309 0 : RETURN_FALSE;
4310 : }
4311 :
4312 1 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4313 :
4314 1 : RETURN_LONG(PQtransactionStatus(pgsql));
4315 : }
4316 : #endif
4317 :
4318 : /* }}} */
4319 :
4320 : /* {{{ proto bool pg_connection_reset(resource connection)
4321 : Reset connection (reconnect) */
4322 : PHP_FUNCTION(pg_connection_reset)
4323 1 : {
4324 : zval *pgsql_link;
4325 1 : int id = -1;
4326 : PGconn *pgsql;
4327 :
4328 1 : if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
4329 : &pgsql_link) == FAILURE) {
4330 0 : RETURN_FALSE;
4331 : }
4332 :
4333 1 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4334 :
4335 1 : PQreset(pgsql);
4336 1 : if (PQstatus(pgsql) == CONNECTION_BAD) {
4337 0 : RETURN_FALSE;
4338 : }
4339 1 : RETURN_TRUE;
4340 : }
4341 :
4342 : /* }}} */
4343 :
4344 : #define PHP_PG_ASYNC_IS_BUSY 1
4345 : #define PHP_PG_ASYNC_REQUEST_CANCEL 2
4346 :
4347 : /* {{{ php_pgsql_flush_query
4348 : */
4349 : static int php_pgsql_flush_query(PGconn *pgsql TSRMLS_DC)
4350 41 : {
4351 : PGresult *res;
4352 41 : int leftover = 0;
4353 :
4354 41 : if (PQ_SETNONBLOCKING(pgsql, 1)) {
4355 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to nonblocking mode");
4356 0 : return -1;
4357 : }
4358 82 : while ((res = PQgetResult(pgsql))) {
4359 0 : PQclear(res);
4360 0 : leftover++;
4361 : }
4362 41 : PQ_SETNONBLOCKING(pgsql, 0);
4363 41 : return leftover;
4364 : }
4365 : /* }}} */
4366 :
4367 : /* {{{ php_pgsql_do_async
4368 : */
4369 : static void php_pgsql_do_async(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
4370 94 : {
4371 : zval *pgsql_link;
4372 94 : int id = -1;
4373 : PGconn *pgsql;
4374 : PGresult *pgsql_result;
4375 :
4376 94 : if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
4377 : &pgsql_link) == FAILURE) {
4378 0 : RETURN_FALSE;
4379 : }
4380 :
4381 94 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4382 :
4383 94 : if (PQ_SETNONBLOCKING(pgsql, 1)) {
4384 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to nonblocking mode");
4385 0 : RETURN_FALSE;
4386 : }
4387 94 : switch(entry_type) {
4388 : case PHP_PG_ASYNC_IS_BUSY:
4389 94 : PQconsumeInput(pgsql);
4390 94 : Z_LVAL_P(return_value) = PQisBusy(pgsql);
4391 94 : Z_TYPE_P(return_value) = IS_LONG;
4392 94 : break;
4393 : case PHP_PG_ASYNC_REQUEST_CANCEL:
4394 0 : Z_LVAL_P(return_value) = PQrequestCancel(pgsql);
4395 0 : Z_TYPE_P(return_value) = IS_LONG;
4396 0 : while ((pgsql_result = PQgetResult(pgsql))) {
4397 0 : PQclear(pgsql_result);
4398 : }
4399 0 : break;
4400 : default:
4401 0 : php_error_docref(NULL TSRMLS_CC, E_ERROR, "PostgreSQL module error, please report this error");
4402 : break;
4403 : }
4404 94 : if (PQ_SETNONBLOCKING(pgsql, 0)) {
4405 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
4406 : }
4407 94 : convert_to_boolean_ex(&return_value);
4408 : }
4409 : /* }}} */
4410 :
4411 : /* {{{ proto bool pg_cancel_query(resource connection)
4412 : Cancel request */
4413 : PHP_FUNCTION(pg_cancel_query)
4414 0 : {
4415 0 : php_pgsql_do_async(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_ASYNC_REQUEST_CANCEL);
4416 0 : }
4417 : /* }}} */
4418 :
4419 : /* {{{ proto bool pg_connection_busy(resource connection)
4420 : Get connection is busy or not */
4421 : PHP_FUNCTION(pg_connection_busy)
4422 94 : {
4423 94 : php_pgsql_do_async(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_ASYNC_IS_BUSY);
4424 94 : }
4425 : /* }}} */
4426 :
4427 : /* {{{ proto bool pg_send_query(resource connection, string query)
4428 : Send asynchronous query */
4429 : PHP_FUNCTION(pg_send_query)
4430 2 : {
4431 : zval *pgsql_link;
4432 : char *query;
4433 : int len;
4434 2 : int id = -1;
4435 : PGconn *pgsql;
4436 : PGresult *res;
4437 2 : int leftover = 0;
4438 :
4439 2 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs",
4440 : &pgsql_link, &query, &len) == FAILURE) {
4441 0 : return;
4442 : }
4443 :
4444 2 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4445 :
4446 2 : if (PQ_SETNONBLOCKING(pgsql, 1)) {
4447 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to nonblocking mode");
4448 0 : RETURN_FALSE;
4449 : }
4450 4 : while ((res = PQgetResult(pgsql))) {
4451 0 : PQclear(res);
4452 0 : leftover = 1;
4453 : }
4454 2 : if (leftover) {
4455 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "There are results on this connection. Call pg_get_result() until it returns FALSE");
4456 : }
4457 2 : if (!PQsendQuery(pgsql, query)) {
4458 0 : if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
4459 0 : PQreset(pgsql);
4460 : }
4461 0 : if (!PQsendQuery(pgsql, query)) {
4462 0 : RETURN_FALSE;
4463 : }
4464 : }
4465 2 : if (PQ_SETNONBLOCKING(pgsql, 0)) {
4466 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
4467 : }
4468 2 : RETURN_TRUE;
4469 : }
4470 : /* }}} */
4471 :
4472 : #if HAVE_PQSENDQUERYPARAMS
4473 : /* {{{ proto bool pg_send_query_params(resource connection, string query, array params)
4474 : Send asynchronous parameterized query */
4475 : PHP_FUNCTION(pg_send_query_params)
4476 2 : {
4477 : zval *pgsql_link, *pv_param_arr, **tmp;
4478 2 : int num_params = 0;
4479 2 : char **params = NULL;
4480 : char *query;
4481 2 : int query_len, id = -1;
4482 : PGconn *pgsql;
4483 : PGresult *res;
4484 2 : int leftover = 0;
4485 :
4486 2 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsa/", &pgsql_link, &query, &query_len, &pv_param_arr) == FAILURE) {
4487 0 : return;
4488 : }
4489 :
4490 2 : if (pgsql_link == NULL && id == -1) {
4491 0 : RETURN_FALSE;
4492 : }
4493 :
4494 2 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4495 :
4496 2 : if (PQ_SETNONBLOCKING(pgsql, 1)) {
4497 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to nonblocking mode");
4498 0 : RETURN_FALSE;
4499 : }
4500 4 : while ((res = PQgetResult(pgsql))) {
4501 0 : PQclear(res);
4502 0 : leftover = 1;
4503 : }
4504 2 : if (leftover) {
4505 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "There are results on this connection. Call pg_get_result() until it returns FALSE");
4506 : }
4507 :
4508 2 : zend_hash_internal_pointer_reset(Z_ARRVAL_P(pv_param_arr));
4509 2 : num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr));
4510 2 : if (num_params > 0) {
4511 2 : int i = 0;
4512 2 : params = (char **)safe_emalloc(sizeof(char *), num_params, 0);
4513 :
4514 5 : for(i = 0; i < num_params; i++) {
4515 3 : if (zend_hash_get_current_data(Z_ARRVAL_P(pv_param_arr), (void **) &tmp) == FAILURE) {
4516 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error getting parameter");
4517 0 : _php_pgsql_free_params(params, num_params);
4518 0 : RETURN_FALSE;
4519 : }
4520 :
4521 3 : if (Z_TYPE_PP(tmp) == IS_NULL) {
4522 0 : params[i] = NULL;
4523 : } else {
4524 3 : zval tmp_val = **tmp;
4525 3 : zval_copy_ctor(&tmp_val);
4526 3 : convert_to_string(&tmp_val);
4527 3 : if (Z_TYPE(tmp_val) != IS_STRING) {
4528 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error converting parameter");
4529 0 : zval_dtor(&tmp_val);
4530 0 : _php_pgsql_free_params(params, num_params);
4531 0 : RETURN_FALSE;
4532 : }
4533 3 : params[i] = estrndup(Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
4534 3 : zval_dtor(&tmp_val);
4535 : }
4536 :
4537 3 : zend_hash_move_forward(Z_ARRVAL_P(pv_param_arr));
4538 : }
4539 : }
4540 :
4541 2 : if (!PQsendQueryParams(pgsql, query, num_params, NULL, (const char * const *)params, NULL, NULL, 0)) {
4542 0 : if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
4543 0 : PQreset(pgsql);
4544 : }
4545 0 : if (!PQsendQueryParams(pgsql, query, num_params, NULL, (const char * const *)params, NULL, NULL, 0)) {
4546 0 : _php_pgsql_free_params(params, num_params);
4547 0 : RETURN_FALSE;
4548 : }
4549 : }
4550 2 : _php_pgsql_free_params(params, num_params);
4551 2 : if (PQ_SETNONBLOCKING(pgsql, 0)) {
4552 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
4553 : }
4554 2 : RETURN_TRUE;
4555 : }
4556 : /* }}} */
4557 : #endif
4558 :
4559 : #if HAVE_PQSENDPREPARE
4560 : /* {{{ proto bool pg_send_prepare(resource connection, string stmtname, string query)
4561 : Asynchronously prepare a query for future execution */
4562 : PHP_FUNCTION(pg_send_prepare)
4563 2 : {
4564 : zval *pgsql_link;
4565 : char *query, *stmtname;
4566 2 : int stmtname_len, query_len, id = -1;
4567 : PGconn *pgsql;
4568 : PGresult *res;
4569 2 : int leftover = 0;
4570 :
4571 2 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &pgsql_link, &stmtname, &stmtname_len, &query, &query_len) == FAILURE) {
4572 0 : return;
4573 : }
4574 :
4575 2 : if (pgsql_link == NULL && id == -1) {
4576 0 : RETURN_FALSE;
4577 : }
4578 :
4579 2 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4580 :
4581 2 : if (PQ_SETNONBLOCKING(pgsql, 1)) {
4582 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to nonblocking mode");
4583 0 : RETURN_FALSE;
4584 : }
4585 4 : while ((res = PQgetResult(pgsql))) {
4586 0 : PQclear(res);
4587 0 : leftover = 1;
4588 : }
4589 2 : if (leftover) {
4590 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "There are results on this connection. Call pg_get_result() until it returns FALSE");
4591 : }
4592 2 : if (!PQsendPrepare(pgsql, stmtname, query, 0, NULL)) {
4593 0 : if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
4594 0 : PQreset(pgsql);
4595 : }
4596 0 : if (!PQsendPrepare(pgsql, stmtname, query, 0, NULL)) {
4597 0 : RETURN_FALSE;
4598 : }
4599 : }
4600 2 : if (PQ_SETNONBLOCKING(pgsql, 0)) {
4601 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
4602 : }
4603 2 : RETURN_TRUE;
4604 : }
4605 : /* }}} */
4606 : #endif
4607 :
4608 : #if HAVE_PQSENDQUERYPREPARED
4609 : /* {{{ proto bool pg_send_execute(resource connection, string stmtname, array params)
4610 : Executes prevriously prepared stmtname asynchronously */
4611 : PHP_FUNCTION(pg_send_execute)
4612 2 : {
4613 : zval *pgsql_link;
4614 : zval *pv_param_arr, **tmp;
4615 2 : int num_params = 0;
4616 2 : char **params = NULL;
4617 : char *stmtname;
4618 2 : int stmtname_len, id = -1;
4619 : PGconn *pgsql;
4620 : PGresult *res;
4621 2 : int leftover = 0;
4622 :
4623 2 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsa", &pgsql_link, &stmtname, &stmtname_len, &pv_param_arr) == FAILURE) {
4624 0 : return;
4625 : }
4626 :
4627 2 : if (pgsql_link == NULL && id == -1) {
4628 0 : RETURN_FALSE;
4629 : }
4630 :
4631 2 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4632 :
4633 2 : if (PQ_SETNONBLOCKING(pgsql, 1)) {
4634 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to nonblocking mode");
4635 0 : RETURN_FALSE;
4636 : }
4637 4 : while ((res = PQgetResult(pgsql))) {
4638 0 : PQclear(res);
4639 0 : leftover = 1;
4640 : }
4641 2 : if (leftover) {
4642 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "There are results on this connection. Call pg_get_result() until it returns FALSE");
4643 : }
4644 :
4645 2 : zend_hash_internal_pointer_reset(Z_ARRVAL_P(pv_param_arr));
4646 2 : num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr));
4647 2 : if (num_params > 0) {
4648 2 : int i = 0;
4649 2 : params = (char **)safe_emalloc(sizeof(char *), num_params, 0);
4650 :
4651 5 : for(i = 0; i < num_params; i++) {
4652 3 : if (zend_hash_get_current_data(Z_ARRVAL_P(pv_param_arr), (void **) &tmp) == FAILURE) {
4653 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error getting parameter");
4654 0 : _php_pgsql_free_params(params, num_params);
4655 0 : RETURN_FALSE;
4656 : }
4657 :
4658 3 : if (Z_TYPE_PP(tmp) == IS_NULL) {
4659 0 : params[i] = NULL;
4660 : } else {
4661 3 : zval tmp_val = **tmp;
4662 3 : zval_copy_ctor(&tmp_val);
4663 3 : convert_to_string(&tmp_val);
4664 3 : if (Z_TYPE(tmp_val) != IS_STRING) {
4665 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error converting parameter");
4666 0 : zval_dtor(&tmp_val);
4667 0 : _php_pgsql_free_params(params, num_params);
4668 0 : RETURN_FALSE;
4669 : }
4670 3 : params[i] = estrndup(Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
4671 3 : zval_dtor(&tmp_val);
4672 : }
4673 :
4674 3 : zend_hash_move_forward(Z_ARRVAL_P(pv_param_arr));
4675 : }
4676 : }
4677 :
4678 2 : if (!PQsendQueryPrepared(pgsql, stmtname, num_params, (const char * const *)params, NULL, NULL, 0)) {
4679 0 : if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
4680 0 : PQreset(pgsql);
4681 : }
4682 0 : if (!PQsendQueryPrepared(pgsql, stmtname, num_params, (const char * const *)params, NULL, NULL, 0)) {
4683 0 : _php_pgsql_free_params(params, num_params);
4684 0 : RETURN_FALSE;
4685 : }
4686 : }
4687 2 : _php_pgsql_free_params(params, num_params);
4688 2 : if (PQ_SETNONBLOCKING(pgsql, 0)) {
4689 0 : php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
4690 : }
4691 2 : RETURN_TRUE;
4692 : }
4693 : /* }}} */
4694 : #endif
4695 :
4696 : /* {{{ proto resource pg_get_result(resource connection)
4697 : Get asynchronous query result */
4698 : PHP_FUNCTION(pg_get_result)
4699 6 : {
4700 : zval *pgsql_link;
4701 6 : int id = -1;
4702 : PGconn *pgsql;
4703 : PGresult *pgsql_result;
4704 : pgsql_result_handle *pg_result;
4705 :
4706 6 : if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r", &pgsql_link) == FAILURE) {
4707 0 : RETURN_FALSE;
4708 : }
4709 :
4710 6 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4711 :
4712 6 : pgsql_result = PQgetResult(pgsql);
4713 6 : if (!pgsql_result) {
4714 : /* no result */
4715 0 : RETURN_FALSE;
4716 : }
4717 6 : pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle));
4718 6 : pg_result->conn = pgsql;
4719 6 : pg_result->result = pgsql_result;
4720 6 : pg_result->row = 0;
4721 6 : ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result);
4722 : }
4723 : /* }}} */
4724 :
4725 : /* {{{ proto mixed pg_result_status(resource result[, long result_type])
4726 : Get status of query result */
4727 : PHP_FUNCTION(pg_result_status)
4728 2 : {
4729 : zval *result;
4730 2 : long result_type = PGSQL_STATUS_LONG;
4731 : ExecStatusType status;
4732 : PGresult *pgsql_result;
4733 : pgsql_result_handle *pg_result;
4734 :
4735 2 : if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r|l",
4736 : &result, &result_type) == FAILURE) {
4737 0 : RETURN_FALSE;
4738 : }
4739 :
4740 2 : ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
4741 :
4742 2 : pgsql_result = pg_result->result;
4743 2 : if (result_type == PGSQL_STATUS_LONG) {
4744 1 : status = PQresultStatus(pgsql_result);
4745 1 : RETURN_LONG((int)status);
4746 : }
4747 1 : else if (result_type == PGSQL_STATUS_STRING) {
4748 1 : RETURN_STRING(PQcmdStatus(pgsql_result), 1);
4749 : }
4750 : else {
4751 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Optional 2nd parameter should be PGSQL_STATUS_LONG or PGSQL_STATUS_STRING");
4752 0 : RETURN_FALSE;
4753 : }
4754 : }
4755 : /* }}} */
4756 :
4757 :
4758 : /* {{{ proto array pg_get_notify([resource connection[, result_type]])
4759 : Get asynchronous notification */
4760 : PHP_FUNCTION(pg_get_notify)
4761 1 : {
4762 : zval *pgsql_link;
4763 1 : int id = -1;
4764 1 : long result_type = PGSQL_ASSOC;
4765 : PGconn *pgsql;
4766 : PGnotify *pgsql_notify;
4767 :
4768 1 : if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r|l",
4769 : &pgsql_link, &result_type) == FAILURE) {
4770 0 : RETURN_FALSE;
4771 : }
4772 :
4773 1 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4774 :
4775 1 : if (!(result_type & PGSQL_BOTH)) {
4776 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid result type");
4777 0 : RETURN_FALSE;
4778 : }
4779 :
4780 1 : PQconsumeInput(pgsql);
4781 1 : pgsql_notify = PQnotifies(pgsql);
4782 1 : if (!pgsql_notify) {
4783 : /* no notify message */
4784 0 : RETURN_FALSE;
4785 : }
4786 1 : array_init(return_value);
4787 1 : if (result_type & PGSQL_NUM) {
4788 0 : add_index_string(return_value, 0, pgsql_notify->relname, 1);
4789 0 : add_index_long(return_value, 1, pgsql_notify->be_pid);
4790 : }
4791 1 : if (result_type & PGSQL_ASSOC) {
4792 1 : add_assoc_string(return_value, "message", pgsql_notify->relname, 1);
4793 1 : add_assoc_long(return_value, "pid", pgsql_notify->be_pid);
4794 : }
4795 1 : PQfreemem(pgsql_notify);
4796 : }
4797 : /* }}} */
4798 :
4799 : /* {{{ proto int pg_get_pid([resource connection)
4800 : Get backend(server) pid */
4801 : PHP_FUNCTION(pg_get_pid)
4802 1 : {
4803 : zval *pgsql_link;
4804 1 : int id = -1;
4805 : PGconn *pgsql;
4806 :
4807 1 : if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
4808 : &pgsql_link) == FAILURE) {
4809 0 : RETURN_FALSE;
4810 : }
4811 :
4812 1 : ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4813 :
4814 1 : RETURN_LONG(PQbackendPID(pgsql));
4815 : }
4816 : /* }}} */
4817 :
4818 : /* {{{ php_pgsql_meta_data
4819 : * TODO: Add meta_data cache for better performance
4820 : */
4821 : PHP_PGSQL_API int php_pgsql_meta_data(PGconn *pg_link, const char *table_name, zval *meta TSRMLS_DC)
4822 50 : {
4823 : PGresult *pg_result;
4824 50 : char *src, *tmp_name, *tmp_name2 = NULL;
4825 50 : smart_str querystr = {0};
4826 : int new_len;
4827 : int i, num_rows;
4828 : zval *elem;
4829 :
4830 50 : if (!*table_name) {
4831 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "The table name must be specified");
4832 0 : return FAILURE;
4833 : }
4834 :
4835 50 : src = estrdup(table_name);
4836 50 : tmp_name = php_strtok_r(src, ".", &tmp_name2);
4837 :
4838 50 : if (!tmp_name2 || !*tmp_name2) {
4839 : /* Default schema */
4840 31 : tmp_name2 = tmp_name;
4841 31 : tmp_name = "public";
4842 : }
4843 :
4844 50 : smart_str_appends(&querystr,
4845 : "SELECT a.attname, a.attnum, t.typname, a.attlen, a.attnotNULL, a.atthasdef, a.attndims "
4846 : "FROM pg_class as c, pg_attribute a, pg_type t, pg_namespace n "
4847 : "WHERE a.attnum > 0 AND a.attrelid = c.oid AND c.relname = '");
4848 50 : tmp_name2 = php_addslashes(tmp_name2, strlen(tmp_name2), &new_len, 0 TSRMLS_CC);
4849 50 : smart_str_appendl(&querystr, tmp_name2, new_len);
4850 :
4851 50 : smart_str_appends(&querystr, "' AND c.relnamespace = n.oid AND n.nspname = '");
4852 50 : tmp_name = php_addslashes(tmp_name, strlen(tmp_name), &new_len, 0 TSRMLS_CC);
4853 50 : smart_str_appendl(&querystr, tmp_name, new_len);
4854 :
4855 50 : smart_str_appends(&querystr, "' AND a.atttypid = t.oid ORDER BY a.attnum;");
4856 50 : smart_str_0(&querystr);
4857 :
4858 50 : efree(tmp_name2);
4859 50 : efree(tmp_name);
4860 50 : efree(src);
4861 :
4862 |