Annotation of embedaddon/php/ext/pgsql/pgsql.c, revision 1.1.1.3
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
1.1.1.3 ! misho 5: | Copyright (c) 1997-2013 The PHP Group |
1.1 misho 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:
1.1.1.2 misho 23: /* $Id$ */
1.1 misho 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:
1.1.1.3 ! misho 425: #if HAVE_PQESCAPE
! 426: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_escape_literal, 0, 0, 0)
! 427: ZEND_ARG_INFO(0, connection)
! 428: ZEND_ARG_INFO(0, data)
! 429: ZEND_END_ARG_INFO()
! 430: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_escape_identifier, 0, 0, 0)
! 431: ZEND_ARG_INFO(0, connection)
! 432: ZEND_ARG_INFO(0, data)
! 433: ZEND_END_ARG_INFO()
! 434: #endif
! 435:
1.1 misho 436: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_result_error, 0, 0, 1)
437: ZEND_ARG_INFO(0, result)
438: ZEND_END_ARG_INFO()
439:
440: #if HAVE_PQRESULTERRORFIELD
441: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_result_error_field, 0, 0, 2)
442: ZEND_ARG_INFO(0, result)
443: ZEND_ARG_INFO(0, fieldcode)
444: ZEND_END_ARG_INFO()
445: #endif
446:
447: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_connection_status, 0, 0, 1)
448: ZEND_ARG_INFO(0, connection)
449: ZEND_END_ARG_INFO()
450:
451: #if HAVE_PGTRANSACTIONSTATUS
452: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_transaction_status, 0, 0, 1)
453: ZEND_ARG_INFO(0, connection)
454: ZEND_END_ARG_INFO()
455: #endif
456:
457: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_connection_reset, 0, 0, 1)
458: ZEND_ARG_INFO(0, connection)
459: ZEND_END_ARG_INFO()
460:
461: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_cancel_query, 0, 0, 1)
462: ZEND_ARG_INFO(0, connection)
463: ZEND_END_ARG_INFO()
464:
465: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_connection_busy, 0, 0, 1)
466: ZEND_ARG_INFO(0, connection)
467: ZEND_END_ARG_INFO()
468:
469: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_send_query, 0, 0, 2)
470: ZEND_ARG_INFO(0, connection)
471: ZEND_ARG_INFO(0, query)
472: ZEND_END_ARG_INFO()
473:
474: #if HAVE_PQSENDQUERYPARAMS
475: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_send_query_params, 0, 0, 3)
476: ZEND_ARG_INFO(0, connection)
477: ZEND_ARG_INFO(0, query)
478: ZEND_ARG_INFO(0, params)
479: ZEND_END_ARG_INFO()
480: #endif
481:
482: #if HAVE_PQSENDPREPARE
483: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_send_prepare, 0, 0, 3)
484: ZEND_ARG_INFO(0, connection)
485: ZEND_ARG_INFO(0, stmtname)
486: ZEND_ARG_INFO(0, query)
487: ZEND_END_ARG_INFO()
488: #endif
489:
490: #if HAVE_PQSENDQUERYPREPARED
491: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_send_execute, 0, 0, 3)
492: ZEND_ARG_INFO(0, connection)
493: ZEND_ARG_INFO(0, stmtname)
494: ZEND_ARG_INFO(0, params)
495: ZEND_END_ARG_INFO()
496: #endif
497:
498: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_get_result, 0, 0, 1)
499: ZEND_ARG_INFO(0, connection)
500: ZEND_END_ARG_INFO()
501:
502: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_result_status, 0, 0, 1)
503: ZEND_ARG_INFO(0, result)
504: ZEND_ARG_INFO(0, result_type)
505: ZEND_END_ARG_INFO()
506:
507: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_get_notify, 0, 0, 0)
508: ZEND_ARG_INFO(0, connection)
509: ZEND_ARG_INFO(0, e)
510: ZEND_END_ARG_INFO()
511:
512: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_get_pid, 0, 0, 0)
513: ZEND_ARG_INFO(0, connection)
514: ZEND_END_ARG_INFO()
515:
516: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_meta_data, 0, 0, 2)
517: ZEND_ARG_INFO(0, db)
518: ZEND_ARG_INFO(0, table)
519: ZEND_END_ARG_INFO()
520:
521: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_convert, 0, 0, 3)
522: ZEND_ARG_INFO(0, db)
523: ZEND_ARG_INFO(0, table)
524: ZEND_ARG_INFO(0, values)
525: ZEND_ARG_INFO(0, options)
526: ZEND_END_ARG_INFO()
527:
528: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_insert, 0, 0, 3)
529: ZEND_ARG_INFO(0, db)
530: ZEND_ARG_INFO(0, table)
531: ZEND_ARG_INFO(0, values)
532: ZEND_ARG_INFO(0, options)
533: ZEND_END_ARG_INFO()
534:
535: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_update, 0, 0, 4)
536: ZEND_ARG_INFO(0, db)
537: ZEND_ARG_INFO(0, table)
538: ZEND_ARG_INFO(0, fields)
539: ZEND_ARG_INFO(0, ids)
540: ZEND_ARG_INFO(0, options)
541: ZEND_END_ARG_INFO()
542:
543: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_delete, 0, 0, 3)
544: ZEND_ARG_INFO(0, db)
545: ZEND_ARG_INFO(0, table)
546: ZEND_ARG_INFO(0, ids)
547: ZEND_ARG_INFO(0, options)
548: ZEND_END_ARG_INFO()
549:
550: ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_select, 0, 0, 3)
551: ZEND_ARG_INFO(0, db)
552: ZEND_ARG_INFO(0, table)
553: ZEND_ARG_INFO(0, ids)
554: ZEND_ARG_INFO(0, options)
555: ZEND_END_ARG_INFO()
556: /* }}} */
557:
558: /* {{{ pgsql_functions[]
559: */
560: const zend_function_entry pgsql_functions[] = {
561: /* connection functions */
562: PHP_FE(pg_connect, arginfo_pg_connect)
563: PHP_FE(pg_pconnect, arginfo_pg_pconnect)
564: PHP_FE(pg_close, arginfo_pg_close)
565: PHP_FE(pg_connection_status, arginfo_pg_connection_status)
566: PHP_FE(pg_connection_busy, arginfo_pg_connection_busy)
567: PHP_FE(pg_connection_reset, arginfo_pg_connection_reset)
568: PHP_FE(pg_host, arginfo_pg_host)
569: PHP_FE(pg_dbname, arginfo_pg_dbname)
570: PHP_FE(pg_port, arginfo_pg_port)
571: PHP_FE(pg_tty, arginfo_pg_tty)
572: PHP_FE(pg_options, arginfo_pg_options)
573: PHP_FE(pg_version, arginfo_pg_version)
574: PHP_FE(pg_ping, arginfo_pg_ping)
575: #if HAVE_PQPARAMETERSTATUS
576: PHP_FE(pg_parameter_status, arginfo_pg_parameter_status)
577: #endif
578: #if HAVE_PGTRANSACTIONSTATUS
579: PHP_FE(pg_transaction_status, arginfo_pg_transaction_status)
580: #endif
581: /* query functions */
582: PHP_FE(pg_query, arginfo_pg_query)
583: #if HAVE_PQEXECPARAMS
584: PHP_FE(pg_query_params, arginfo_pg_query_params)
585: #endif
586: #if HAVE_PQPREPARE
587: PHP_FE(pg_prepare, arginfo_pg_prepare)
588: #endif
589: #if HAVE_PQEXECPREPARED
590: PHP_FE(pg_execute, arginfo_pg_execute)
591: #endif
592: PHP_FE(pg_send_query, arginfo_pg_send_query)
593: #if HAVE_PQSENDQUERYPARAMS
594: PHP_FE(pg_send_query_params, arginfo_pg_send_query_params)
595: #endif
596: #if HAVE_PQSENDPREPARE
597: PHP_FE(pg_send_prepare, arginfo_pg_send_prepare)
598: #endif
599: #if HAVE_PQSENDQUERYPREPARED
600: PHP_FE(pg_send_execute, arginfo_pg_send_execute)
601: #endif
602: PHP_FE(pg_cancel_query, arginfo_pg_cancel_query)
603: /* result functions */
604: PHP_FE(pg_fetch_result, arginfo_pg_fetch_result)
605: PHP_FE(pg_fetch_row, arginfo_pg_fetch_row)
606: PHP_FE(pg_fetch_assoc, arginfo_pg_fetch_assoc)
607: PHP_FE(pg_fetch_array, arginfo_pg_fetch_array)
608: PHP_FE(pg_fetch_object, arginfo_pg_fetch_object)
609: PHP_FE(pg_fetch_all, arginfo_pg_fetch_all)
610: PHP_FE(pg_fetch_all_columns, arginfo_pg_fetch_all_columns)
611: #if HAVE_PQCMDTUPLES
612: PHP_FE(pg_affected_rows,arginfo_pg_affected_rows)
613: #endif
614: PHP_FE(pg_get_result, arginfo_pg_get_result)
615: PHP_FE(pg_result_seek, arginfo_pg_result_seek)
616: PHP_FE(pg_result_status,arginfo_pg_result_status)
617: PHP_FE(pg_free_result, arginfo_pg_free_result)
618: PHP_FE(pg_last_oid, arginfo_pg_last_oid)
619: PHP_FE(pg_num_rows, arginfo_pg_num_rows)
620: PHP_FE(pg_num_fields, arginfo_pg_num_fields)
621: PHP_FE(pg_field_name, arginfo_pg_field_name)
622: PHP_FE(pg_field_num, arginfo_pg_field_num)
623: PHP_FE(pg_field_size, arginfo_pg_field_size)
624: PHP_FE(pg_field_type, arginfo_pg_field_type)
625: PHP_FE(pg_field_type_oid, arginfo_pg_field_type_oid)
626: PHP_FE(pg_field_prtlen, arginfo_pg_field_prtlen)
627: PHP_FE(pg_field_is_null,arginfo_pg_field_is_null)
628: #ifdef HAVE_PQFTABLE
629: PHP_FE(pg_field_table, arginfo_pg_field_table)
630: #endif
631: /* async message function */
632: PHP_FE(pg_get_notify, arginfo_pg_get_notify)
633: PHP_FE(pg_get_pid, arginfo_pg_get_pid)
634: /* error message functions */
635: PHP_FE(pg_result_error, arginfo_pg_result_error)
636: #if HAVE_PQRESULTERRORFIELD
637: PHP_FE(pg_result_error_field, arginfo_pg_result_error_field)
638: #endif
639: PHP_FE(pg_last_error, arginfo_pg_last_error)
640: PHP_FE(pg_last_notice, arginfo_pg_last_notice)
641: /* copy functions */
642: PHP_FE(pg_put_line, arginfo_pg_put_line)
643: PHP_FE(pg_end_copy, arginfo_pg_end_copy)
644: PHP_FE(pg_copy_to, arginfo_pg_copy_to)
645: PHP_FE(pg_copy_from, arginfo_pg_copy_from)
646: /* debug functions */
647: PHP_FE(pg_trace, arginfo_pg_trace)
648: PHP_FE(pg_untrace, arginfo_pg_untrace)
649: /* large object functions */
650: PHP_FE(pg_lo_create, arginfo_pg_lo_create)
651: PHP_FE(pg_lo_unlink, arginfo_pg_lo_unlink)
652: PHP_FE(pg_lo_open, arginfo_pg_lo_open)
653: PHP_FE(pg_lo_close, arginfo_pg_lo_close)
654: PHP_FE(pg_lo_read, arginfo_pg_lo_read)
655: PHP_FE(pg_lo_write, arginfo_pg_lo_write)
656: PHP_FE(pg_lo_read_all, arginfo_pg_lo_read_all)
657: PHP_FE(pg_lo_import, arginfo_pg_lo_import)
658: PHP_FE(pg_lo_export, arginfo_pg_lo_export)
659: PHP_FE(pg_lo_seek, arginfo_pg_lo_seek)
660: PHP_FE(pg_lo_tell, arginfo_pg_lo_tell)
661: /* utility functions */
662: #if HAVE_PQESCAPE
663: PHP_FE(pg_escape_string, arginfo_pg_escape_string)
664: PHP_FE(pg_escape_bytea, arginfo_pg_escape_bytea)
665: PHP_FE(pg_unescape_bytea, arginfo_pg_unescape_bytea)
1.1.1.3 ! misho 666: PHP_FE(pg_escape_literal, arginfo_pg_escape_literal)
! 667: PHP_FE(pg_escape_identifier, arginfo_pg_escape_identifier)
1.1 misho 668: #endif
669: #if HAVE_PQSETERRORVERBOSITY
670: PHP_FE(pg_set_error_verbosity, arginfo_pg_set_error_verbosity)
671: #endif
672: #if HAVE_PQCLIENTENCODING
673: PHP_FE(pg_client_encoding, arginfo_pg_client_encoding)
674: PHP_FE(pg_set_client_encoding, arginfo_pg_set_client_encoding)
675: #endif
676: /* misc function */
677: PHP_FE(pg_meta_data, arginfo_pg_meta_data)
678: PHP_FE(pg_convert, arginfo_pg_convert)
679: PHP_FE(pg_insert, arginfo_pg_insert)
680: PHP_FE(pg_update, arginfo_pg_update)
681: PHP_FE(pg_delete, arginfo_pg_delete)
682: PHP_FE(pg_select, arginfo_pg_select)
683: /* aliases for downwards compatibility */
684: PHP_FALIAS(pg_exec, pg_query, arginfo_pg_query)
685: PHP_FALIAS(pg_getlastoid, pg_last_oid, arginfo_pg_last_oid)
686: #if HAVE_PQCMDTUPLES
687: PHP_FALIAS(pg_cmdtuples, pg_affected_rows, arginfo_pg_affected_rows)
688: #endif
689: PHP_FALIAS(pg_errormessage, pg_last_error, arginfo_pg_last_error)
690: PHP_FALIAS(pg_numrows, pg_num_rows, arginfo_pg_num_rows)
691: PHP_FALIAS(pg_numfields, pg_num_fields, arginfo_pg_num_fields)
692: PHP_FALIAS(pg_fieldname, pg_field_name, arginfo_pg_field_name)
693: PHP_FALIAS(pg_fieldsize, pg_field_size, arginfo_pg_field_size)
694: PHP_FALIAS(pg_fieldtype, pg_field_type, arginfo_pg_field_type)
695: PHP_FALIAS(pg_fieldnum, pg_field_num, arginfo_pg_field_num)
696: PHP_FALIAS(pg_fieldprtlen, pg_field_prtlen, arginfo_pg_field_prtlen)
697: PHP_FALIAS(pg_fieldisnull, pg_field_is_null, arginfo_pg_field_is_null)
698: PHP_FALIAS(pg_freeresult, pg_free_result, arginfo_pg_free_result)
699: PHP_FALIAS(pg_result, pg_fetch_result, arginfo_pg_get_result)
700: PHP_FALIAS(pg_loreadall, pg_lo_read_all, arginfo_pg_lo_read_all)
701: PHP_FALIAS(pg_locreate, pg_lo_create, arginfo_pg_lo_create)
702: PHP_FALIAS(pg_lounlink, pg_lo_unlink, arginfo_pg_lo_unlink)
703: PHP_FALIAS(pg_loopen, pg_lo_open, arginfo_pg_lo_open)
704: PHP_FALIAS(pg_loclose, pg_lo_close, arginfo_pg_lo_close)
705: PHP_FALIAS(pg_loread, pg_lo_read, arginfo_pg_lo_read)
706: PHP_FALIAS(pg_lowrite, pg_lo_write, arginfo_pg_lo_write)
707: PHP_FALIAS(pg_loimport, pg_lo_import, arginfo_pg_lo_import)
708: PHP_FALIAS(pg_loexport, pg_lo_export, arginfo_pg_lo_export)
709: #if HAVE_PQCLIENTENCODING
710: PHP_FALIAS(pg_clientencoding, pg_client_encoding, arginfo_pg_client_encoding)
711: PHP_FALIAS(pg_setclientencoding, pg_set_client_encoding, arginfo_pg_set_client_encoding)
712: #endif
713: PHP_FE_END
714: };
715: /* }}} */
716:
717: /* {{{ pgsql_module_entry
718: */
719: zend_module_entry pgsql_module_entry = {
720: STANDARD_MODULE_HEADER,
721: "pgsql",
722: pgsql_functions,
723: PHP_MINIT(pgsql),
724: PHP_MSHUTDOWN(pgsql),
725: PHP_RINIT(pgsql),
726: PHP_RSHUTDOWN(pgsql),
727: PHP_MINFO(pgsql),
728: NO_VERSION_YET,
729: PHP_MODULE_GLOBALS(pgsql),
730: PHP_GINIT(pgsql),
731: NULL,
732: NULL,
733: STANDARD_MODULE_PROPERTIES_EX
734: };
735: /* }}} */
736:
737: #ifdef COMPILE_DL_PGSQL
738: ZEND_GET_MODULE(pgsql)
739: #endif
740:
741: static int le_link, le_plink, le_result, le_lofp, le_string;
742:
743: /* {{{ _php_pgsql_trim_message */
744: static char * _php_pgsql_trim_message(const char *message, int *len)
745: {
746: register int i = strlen(message)-1;
747:
748: if (i>1 && (message[i-1] == '\r' || message[i-1] == '\n') && message[i] == '.') {
749: --i;
750: }
751: while (i>0 && (message[i] == '\r' || message[i] == '\n')) {
752: --i;
753: }
754: ++i;
755: if (len) {
756: *len = i;
757: }
758: return estrndup(message, i);
759: }
760: /* }}} */
761:
762: /* {{{ _php_pgsql_trim_result */
763: static inline char * _php_pgsql_trim_result(PGconn * pgsql, char **buf)
764: {
765: return *buf = _php_pgsql_trim_message(PQerrorMessage(pgsql), NULL);
766: }
767: /* }}} */
768:
769: #define PQErrorMessageTrim(pgsql, buf) _php_pgsql_trim_result(pgsql, buf)
770:
771: #define PHP_PQ_ERROR(text, pgsql) { \
772: char *msgbuf = _php_pgsql_trim_message(PQerrorMessage(pgsql), NULL); \
773: php_error_docref(NULL TSRMLS_CC, E_WARNING, text, msgbuf); \
774: efree(msgbuf); \
775: } \
776:
777: /* {{{ php_pgsql_set_default_link
778: */
779: static void php_pgsql_set_default_link(int id TSRMLS_DC)
780: {
781: zend_list_addref(id);
782:
783: if (PGG(default_link) != -1) {
784: zend_list_delete(PGG(default_link));
785: }
786:
787: PGG(default_link) = id;
788: }
789: /* }}} */
790:
791: /* {{{ _close_pgsql_link
792: */
793: static void _close_pgsql_link(zend_rsrc_list_entry *rsrc TSRMLS_DC)
794: {
795: PGconn *link = (PGconn *)rsrc->ptr;
796: PGresult *res;
797:
798: while ((res = PQgetResult(link))) {
799: PQclear(res);
800: }
801: PQfinish(link);
802: PGG(num_links)--;
803: }
804: /* }}} */
805:
806: /* {{{ _close_pgsql_plink
807: */
808: static void _close_pgsql_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC)
809: {
810: PGconn *link = (PGconn *)rsrc->ptr;
811: PGresult *res;
812:
813: while ((res = PQgetResult(link))) {
814: PQclear(res);
815: }
816: PQfinish(link);
817: PGG(num_persistent)--;
818: PGG(num_links)--;
819: }
820: /* }}} */
821:
822: /* {{{ _php_pgsql_notice_handler
823: */
824: static void _php_pgsql_notice_handler(void *resource_id, const char *message)
825: {
826: php_pgsql_notice *notice;
827:
828: TSRMLS_FETCH();
829: if (! PGG(ignore_notices)) {
830: notice = (php_pgsql_notice *)emalloc(sizeof(php_pgsql_notice));
1.1.1.3 ! misho 831: notice->message = _php_pgsql_trim_message(message, (int *)¬ice->len);
1.1 misho 832: if (PGG(log_notices)) {
833: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s", notice->message);
834: }
835: zend_hash_index_update(&PGG(notices), (ulong)resource_id, (void **)¬ice, sizeof(php_pgsql_notice *), NULL);
836: }
837: }
838: /* }}} */
839:
840: #define PHP_PGSQL_NOTICE_PTR_DTOR (void (*)(void *))_php_pgsql_notice_ptr_dtor
841:
842: /* {{{ _php_pgsql_notice_dtor
843: */
844: static void _php_pgsql_notice_ptr_dtor(void **ptr)
845: {
846: php_pgsql_notice *notice = (php_pgsql_notice *)*ptr;
847: if (notice) {
848: efree(notice->message);
849: efree(notice);
850: notice = NULL;
851: }
852: }
853: /* }}} */
854:
855: /* {{{ _rollback_transactions
856: */
857: static int _rollback_transactions(zend_rsrc_list_entry *rsrc TSRMLS_DC)
858: {
859: PGconn *link;
860: PGresult *res;
861: int orig;
862:
863: if (Z_TYPE_P(rsrc) != le_plink)
864: return 0;
865:
866: link = (PGconn *) rsrc->ptr;
867:
868: if (PQ_SETNONBLOCKING(link, 0)) {
869: php_error_docref("ref.pgsql" TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
870: return -1;
871: }
872:
873: while ((res = PQgetResult(link))) {
874: PQclear(res);
875: }
876: #if HAVE_PGTRANSACTIONSTATUS && HAVE_PQPROTOCOLVERSION
877: if ((PQprotocolVersion(link) >= 3 && PQtransactionStatus(link) != PQTRANS_IDLE) || PQprotocolVersion(link) < 3)
878: #endif
879: {
880: orig = PGG(ignore_notices);
881: PGG(ignore_notices) = 1;
882: #if HAVE_PGTRANSACTIONSTATUS && HAVE_PQPROTOCOLVERSION
883: res = PQexec(link,"ROLLBACK;");
884: #else
885: res = PQexec(link,"BEGIN;");
886: PQclear(res);
887: res = PQexec(link,"ROLLBACK;");
888: #endif
889: PQclear(res);
890: PGG(ignore_notices) = orig;
891: }
892:
893: return 0;
894: }
895: /* }}} */
896:
897: /* {{{ _free_ptr
898: */
899: static void _free_ptr(zend_rsrc_list_entry *rsrc TSRMLS_DC)
900: {
901: pgLofp *lofp = (pgLofp *)rsrc->ptr;
902: efree(lofp);
903: }
904: /* }}} */
905:
906: /* {{{ _free_result
907: */
908: static void _free_result(zend_rsrc_list_entry *rsrc TSRMLS_DC)
909: {
910: pgsql_result_handle *pg_result = (pgsql_result_handle *)rsrc->ptr;
911:
912: PQclear(pg_result->result);
913: efree(pg_result);
914: }
915: /* }}} */
916:
917: /* {{{ PHP_INI
918: */
919: PHP_INI_BEGIN()
920: STD_PHP_INI_BOOLEAN( "pgsql.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_persistent, zend_pgsql_globals, pgsql_globals)
921: STD_PHP_INI_ENTRY_EX("pgsql.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_persistent, zend_pgsql_globals, pgsql_globals, display_link_numbers)
922: STD_PHP_INI_ENTRY_EX("pgsql.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_pgsql_globals, pgsql_globals, display_link_numbers)
923: STD_PHP_INI_BOOLEAN( "pgsql.auto_reset_persistent", "0", PHP_INI_SYSTEM, OnUpdateBool, auto_reset_persistent, zend_pgsql_globals, pgsql_globals)
924: STD_PHP_INI_BOOLEAN( "pgsql.ignore_notice", "0", PHP_INI_ALL, OnUpdateBool, ignore_notices, zend_pgsql_globals, pgsql_globals)
925: STD_PHP_INI_BOOLEAN( "pgsql.log_notice", "0", PHP_INI_ALL, OnUpdateBool, log_notices, zend_pgsql_globals, pgsql_globals)
926: PHP_INI_END()
927: /* }}} */
928:
929: /* {{{ PHP_GINIT_FUNCTION
930: */
931: static PHP_GINIT_FUNCTION(pgsql)
932: {
933: memset(pgsql_globals, 0, sizeof(zend_pgsql_globals));
934: /* Initilize notice message hash at MINIT only */
935: zend_hash_init_ex(&pgsql_globals->notices, 0, NULL, PHP_PGSQL_NOTICE_PTR_DTOR, 1, 0);
936: }
937: /* }}} */
938:
939: /* {{{ PHP_MINIT_FUNCTION
940: */
941: PHP_MINIT_FUNCTION(pgsql)
942: {
943: REGISTER_INI_ENTRIES();
944:
945: le_link = zend_register_list_destructors_ex(_close_pgsql_link, NULL, "pgsql link", module_number);
946: le_plink = zend_register_list_destructors_ex(NULL, _close_pgsql_plink, "pgsql link persistent", module_number);
947: le_result = zend_register_list_destructors_ex(_free_result, NULL, "pgsql result", module_number);
948: le_lofp = zend_register_list_destructors_ex(_free_ptr, NULL, "pgsql large object", module_number);
949: le_string = zend_register_list_destructors_ex(_free_ptr, NULL, "pgsql string", module_number);
1.1.1.3 ! misho 950: #if HAVE_PG_CONFIG_H
! 951: /* PG_VERSION - libpq version */
! 952: REGISTER_STRING_CONSTANT("PGSQL_LIBPQ_VERSION", PG_VERSION, CONST_CS | CONST_PERSISTENT);
! 953: REGISTER_STRING_CONSTANT("PGSQL_LIBPQ_VERSION_STR", PG_VERSION_STR, CONST_CS | CONST_PERSISTENT);
! 954: #endif
1.1 misho 955: /* For connection option */
956: REGISTER_LONG_CONSTANT("PGSQL_CONNECT_FORCE_NEW", PGSQL_CONNECT_FORCE_NEW, CONST_CS | CONST_PERSISTENT);
957: /* For pg_fetch_array() */
958: REGISTER_LONG_CONSTANT("PGSQL_ASSOC", PGSQL_ASSOC, CONST_CS | CONST_PERSISTENT);
959: REGISTER_LONG_CONSTANT("PGSQL_NUM", PGSQL_NUM, CONST_CS | CONST_PERSISTENT);
960: REGISTER_LONG_CONSTANT("PGSQL_BOTH", PGSQL_BOTH, CONST_CS | CONST_PERSISTENT);
961: /* For pg_connection_status() */
962: REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_BAD", CONNECTION_BAD, CONST_CS | CONST_PERSISTENT);
963: REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_OK", CONNECTION_OK, CONST_CS | CONST_PERSISTENT);
964: #if HAVE_PGTRANSACTIONSTATUS
965: /* For pg_transaction_status() */
966: REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_IDLE", PQTRANS_IDLE, CONST_CS | CONST_PERSISTENT);
967: REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_ACTIVE", PQTRANS_ACTIVE, CONST_CS | CONST_PERSISTENT);
968: REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_INTRANS", PQTRANS_INTRANS, CONST_CS | CONST_PERSISTENT);
969: REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_INERROR", PQTRANS_INERROR, CONST_CS | CONST_PERSISTENT);
970: REGISTER_LONG_CONSTANT("PGSQL_TRANSACTION_UNKNOWN", PQTRANS_UNKNOWN, CONST_CS | CONST_PERSISTENT);
971: #endif
972: #if HAVE_PQSETERRORVERBOSITY
973: /* For pg_set_error_verbosity() */
974: REGISTER_LONG_CONSTANT("PGSQL_ERRORS_TERSE", PQERRORS_TERSE, CONST_CS | CONST_PERSISTENT);
975: REGISTER_LONG_CONSTANT("PGSQL_ERRORS_DEFAULT", PQERRORS_DEFAULT, CONST_CS | CONST_PERSISTENT);
976: REGISTER_LONG_CONSTANT("PGSQL_ERRORS_VERBOSE", PQERRORS_VERBOSE, CONST_CS | CONST_PERSISTENT);
977: #endif
978: /* For lo_seek() */
979: REGISTER_LONG_CONSTANT("PGSQL_SEEK_SET", SEEK_SET, CONST_CS | CONST_PERSISTENT);
980: REGISTER_LONG_CONSTANT("PGSQL_SEEK_CUR", SEEK_CUR, CONST_CS | CONST_PERSISTENT);
981: REGISTER_LONG_CONSTANT("PGSQL_SEEK_END", SEEK_END, CONST_CS | CONST_PERSISTENT);
982: /* For pg_result_status() return value type */
983: REGISTER_LONG_CONSTANT("PGSQL_STATUS_LONG", PGSQL_STATUS_LONG, CONST_CS | CONST_PERSISTENT);
984: REGISTER_LONG_CONSTANT("PGSQL_STATUS_STRING", PGSQL_STATUS_STRING, CONST_CS | CONST_PERSISTENT);
985: /* For pg_result_status() return value */
986: REGISTER_LONG_CONSTANT("PGSQL_EMPTY_QUERY", PGRES_EMPTY_QUERY, CONST_CS | CONST_PERSISTENT);
987: REGISTER_LONG_CONSTANT("PGSQL_COMMAND_OK", PGRES_COMMAND_OK, CONST_CS | CONST_PERSISTENT);
988: REGISTER_LONG_CONSTANT("PGSQL_TUPLES_OK", PGRES_TUPLES_OK, CONST_CS | CONST_PERSISTENT);
989: REGISTER_LONG_CONSTANT("PGSQL_COPY_OUT", PGRES_COPY_OUT, CONST_CS | CONST_PERSISTENT);
990: REGISTER_LONG_CONSTANT("PGSQL_COPY_IN", PGRES_COPY_IN, CONST_CS | CONST_PERSISTENT);
991: REGISTER_LONG_CONSTANT("PGSQL_BAD_RESPONSE", PGRES_BAD_RESPONSE, CONST_CS | CONST_PERSISTENT);
992: REGISTER_LONG_CONSTANT("PGSQL_NONFATAL_ERROR", PGRES_NONFATAL_ERROR, CONST_CS | CONST_PERSISTENT);
993: REGISTER_LONG_CONSTANT("PGSQL_FATAL_ERROR", PGRES_FATAL_ERROR, CONST_CS | CONST_PERSISTENT);
994: #if HAVE_PQRESULTERRORFIELD
995: /* For pg_result_error_field() field codes */
996: REGISTER_LONG_CONSTANT("PGSQL_DIAG_SEVERITY", PG_DIAG_SEVERITY, CONST_CS | CONST_PERSISTENT);
997: REGISTER_LONG_CONSTANT("PGSQL_DIAG_SQLSTATE", PG_DIAG_SQLSTATE, CONST_CS | CONST_PERSISTENT);
998: REGISTER_LONG_CONSTANT("PGSQL_DIAG_MESSAGE_PRIMARY", PG_DIAG_MESSAGE_PRIMARY, CONST_CS | CONST_PERSISTENT);
999: REGISTER_LONG_CONSTANT("PGSQL_DIAG_MESSAGE_DETAIL", PG_DIAG_MESSAGE_DETAIL, CONST_CS | CONST_PERSISTENT);
1000: REGISTER_LONG_CONSTANT("PGSQL_DIAG_MESSAGE_HINT", PG_DIAG_MESSAGE_HINT, CONST_CS | CONST_PERSISTENT);
1001: REGISTER_LONG_CONSTANT("PGSQL_DIAG_STATEMENT_POSITION", PG_DIAG_STATEMENT_POSITION, CONST_CS | CONST_PERSISTENT);
1002: #ifdef PG_DIAG_INTERNAL_POSITION
1003: REGISTER_LONG_CONSTANT("PGSQL_DIAG_INTERNAL_POSITION", PG_DIAG_INTERNAL_POSITION, CONST_CS | CONST_PERSISTENT);
1004: #endif
1005: #ifdef PG_DIAG_INTERNAL_QUERY
1006: REGISTER_LONG_CONSTANT("PGSQL_DIAG_INTERNAL_QUERY", PG_DIAG_INTERNAL_QUERY, CONST_CS | CONST_PERSISTENT);
1007: #endif
1008: REGISTER_LONG_CONSTANT("PGSQL_DIAG_CONTEXT", PG_DIAG_CONTEXT, CONST_CS | CONST_PERSISTENT);
1009: REGISTER_LONG_CONSTANT("PGSQL_DIAG_SOURCE_FILE", PG_DIAG_SOURCE_FILE, CONST_CS | CONST_PERSISTENT);
1010: REGISTER_LONG_CONSTANT("PGSQL_DIAG_SOURCE_LINE", PG_DIAG_SOURCE_LINE, CONST_CS | CONST_PERSISTENT);
1011: REGISTER_LONG_CONSTANT("PGSQL_DIAG_SOURCE_FUNCTION", PG_DIAG_SOURCE_FUNCTION, CONST_CS | CONST_PERSISTENT);
1012: #endif
1013: /* pg_convert options */
1014: REGISTER_LONG_CONSTANT("PGSQL_CONV_IGNORE_DEFAULT", PGSQL_CONV_IGNORE_DEFAULT, CONST_CS | CONST_PERSISTENT);
1015: REGISTER_LONG_CONSTANT("PGSQL_CONV_FORCE_NULL", PGSQL_CONV_FORCE_NULL, CONST_CS | CONST_PERSISTENT);
1016: REGISTER_LONG_CONSTANT("PGSQL_CONV_IGNORE_NOT_NULL", PGSQL_CONV_IGNORE_NOT_NULL, CONST_CS | CONST_PERSISTENT);
1017: /* pg_insert/update/delete/select options */
1018: REGISTER_LONG_CONSTANT("PGSQL_DML_NO_CONV", PGSQL_DML_NO_CONV, CONST_CS | CONST_PERSISTENT);
1019: REGISTER_LONG_CONSTANT("PGSQL_DML_EXEC", PGSQL_DML_EXEC, CONST_CS | CONST_PERSISTENT);
1020: REGISTER_LONG_CONSTANT("PGSQL_DML_ASYNC", PGSQL_DML_ASYNC, CONST_CS | CONST_PERSISTENT);
1021: REGISTER_LONG_CONSTANT("PGSQL_DML_STRING", PGSQL_DML_STRING, CONST_CS | CONST_PERSISTENT);
1022: return SUCCESS;
1023: }
1024: /* }}} */
1025:
1026: /* {{{ PHP_MSHUTDOWN_FUNCTION
1027: */
1028: PHP_MSHUTDOWN_FUNCTION(pgsql)
1029: {
1030: UNREGISTER_INI_ENTRIES();
1031: zend_hash_destroy(&PGG(notices));
1032:
1033: return SUCCESS;
1034: }
1035: /* }}} */
1036:
1037: /* {{{ PHP_RINIT_FUNCTION
1038: */
1039: PHP_RINIT_FUNCTION(pgsql)
1040: {
1041: PGG(default_link)=-1;
1042: PGG(num_links) = PGG(num_persistent);
1043: return SUCCESS;
1044: }
1045: /* }}} */
1046:
1047: /* {{{ PHP_RSHUTDOWN_FUNCTION
1048: */
1049: PHP_RSHUTDOWN_FUNCTION(pgsql)
1050: {
1051: /* clean up notice messages */
1052: zend_hash_clean(&PGG(notices));
1053: /* clean up persistent connection */
1054: zend_hash_apply(&EG(persistent_list), (apply_func_t) _rollback_transactions TSRMLS_CC);
1055: return SUCCESS;
1056: }
1057: /* }}} */
1058:
1059: /* {{{ PHP_MINFO_FUNCTION
1060: */
1061: PHP_MINFO_FUNCTION(pgsql)
1062: {
1063: char buf[256];
1064:
1065: php_info_print_table_start();
1066: php_info_print_table_header(2, "PostgreSQL Support", "enabled");
1067: #if HAVE_PG_CONFIG_H
1068: php_info_print_table_row(2, "PostgreSQL(libpq) Version", PG_VERSION);
1.1.1.3 ! misho 1069: php_info_print_table_row(2, "PostgreSQL(libpq) ", PG_VERSION_STR);
1.1 misho 1070: #ifdef HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT
1071: php_info_print_table_row(2, "Multibyte character support", "enabled");
1072: #else
1073: php_info_print_table_row(2, "Multibyte character support", "disabled");
1074: #endif
1075: #ifdef USE_SSL
1076: php_info_print_table_row(2, "SSL support", "enabled");
1077: #else
1078: php_info_print_table_row(2, "SSL support", "disabled");
1079: #endif
1080: #endif /* HAVE_PG_CONFIG_H */
1081: snprintf(buf, sizeof(buf), "%ld", PGG(num_persistent));
1082: php_info_print_table_row(2, "Active Persistent Links", buf);
1083: snprintf(buf, sizeof(buf), "%ld", PGG(num_links));
1084: php_info_print_table_row(2, "Active Links", buf);
1085: php_info_print_table_end();
1086:
1087: DISPLAY_INI_ENTRIES();
1088: }
1089: /* }}} */
1090:
1091:
1092: /* {{{ php_pgsql_do_connect
1093: */
1094: static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
1095: {
1096: char *host=NULL,*port=NULL,*options=NULL,*tty=NULL,*dbname=NULL,*connstring=NULL;
1097: PGconn *pgsql;
1098: smart_str str = {0};
1099: zval **args[5];
1100: int i, connect_type = 0;
1101: PGresult *pg_result;
1102:
1103: if (ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 5
1104: || zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
1105: WRONG_PARAM_COUNT;
1106: }
1107:
1108: smart_str_appends(&str, "pgsql");
1109:
1110: for (i = 0; i < ZEND_NUM_ARGS(); i++) {
1111: /* make sure that the PGSQL_CONNECT_FORCE_NEW bit is not part of the hash so that subsequent connections
1112: * can re-use this connection. Bug #39979
1113: */
1114: if (i == 1 && ZEND_NUM_ARGS() == 2 && Z_TYPE_PP(args[i]) == IS_LONG) {
1115: if (Z_LVAL_PP(args[1]) == PGSQL_CONNECT_FORCE_NEW) {
1116: continue;
1117: } else if (Z_LVAL_PP(args[1]) & PGSQL_CONNECT_FORCE_NEW) {
1118: smart_str_append_long(&str, Z_LVAL_PP(args[1]) ^ PGSQL_CONNECT_FORCE_NEW);
1119: }
1120: }
1121: convert_to_string_ex(args[i]);
1122: smart_str_appendc(&str, '_');
1123: smart_str_appendl(&str, Z_STRVAL_PP(args[i]), Z_STRLEN_PP(args[i]));
1124: }
1125:
1126: smart_str_0(&str);
1127:
1128: if (ZEND_NUM_ARGS() == 1) { /* new style, using connection string */
1129: connstring = Z_STRVAL_PP(args[0]);
1130: } else if (ZEND_NUM_ARGS() == 2 ) { /* Safe to add conntype_option, since 2 args was illegal */
1131: connstring = Z_STRVAL_PP(args[0]);
1132: convert_to_long_ex(args[1]);
1133: connect_type = Z_LVAL_PP(args[1]);
1134: } else {
1135: host = Z_STRVAL_PP(args[0]);
1136: port = Z_STRVAL_PP(args[1]);
1137: dbname = Z_STRVAL_PP(args[ZEND_NUM_ARGS()-1]);
1138:
1139: switch (ZEND_NUM_ARGS()) {
1140: case 5:
1141: tty = Z_STRVAL_PP(args[3]);
1142: /* fall through */
1143: case 4:
1144: options = Z_STRVAL_PP(args[2]);
1145: break;
1146: }
1147: }
1148:
1149: if (persistent && PGG(allow_persistent)) {
1150: zend_rsrc_list_entry *le;
1151:
1152: /* try to find if we already have this link in our persistent list */
1153: if (zend_hash_find(&EG(persistent_list), str.c, str.len+1, (void **) &le)==FAILURE) { /* we don't */
1154: zend_rsrc_list_entry new_le;
1155:
1156: if (PGG(max_links)!=-1 && PGG(num_links)>=PGG(max_links)) {
1157: php_error_docref(NULL TSRMLS_CC, E_WARNING,
1158: "Cannot create new link. Too many open links (%ld)", PGG(num_links));
1159: goto err;
1160: }
1161: if (PGG(max_persistent)!=-1 && PGG(num_persistent)>=PGG(max_persistent)) {
1162: php_error_docref(NULL TSRMLS_CC, E_WARNING,
1163: "Cannot create new link. Too many open persistent links (%ld)", PGG(num_persistent));
1164: goto err;
1165: }
1166:
1167: /* create the link */
1168: if (connstring) {
1169: pgsql=PQconnectdb(connstring);
1170: } else {
1171: pgsql=PQsetdb(host,port,options,tty,dbname);
1172: }
1173: if (pgsql==NULL || PQstatus(pgsql)==CONNECTION_BAD) {
1174: PHP_PQ_ERROR("Unable to connect to PostgreSQL server: %s", pgsql)
1175: if (pgsql) {
1176: PQfinish(pgsql);
1177: }
1178: goto err;
1179: }
1180:
1181: /* hash it up */
1182: Z_TYPE(new_le) = le_plink;
1183: new_le.ptr = pgsql;
1184: if (zend_hash_update(&EG(persistent_list), str.c, str.len+1, (void *) &new_le, sizeof(zend_rsrc_list_entry), NULL)==FAILURE) {
1185: goto err;
1186: }
1187: PGG(num_links)++;
1188: PGG(num_persistent)++;
1189: } else { /* we do */
1190: if (Z_TYPE_P(le) != le_plink) {
1191: RETURN_FALSE;
1192: }
1193: /* ensure that the link did not die */
1194: if (PGG(auto_reset_persistent) & 1) {
1195: /* need to send & get something from backend to
1196: make sure we catch CONNECTION_BAD everytime */
1197: PGresult *pg_result;
1198: pg_result = PQexec(le->ptr, "select 1");
1199: PQclear(pg_result);
1200: }
1201: if (PQstatus(le->ptr)==CONNECTION_BAD) { /* the link died */
1202: if (le->ptr == NULL) {
1203: if (connstring) {
1204: le->ptr=PQconnectdb(connstring);
1205: } else {
1206: le->ptr=PQsetdb(host,port,options,tty,dbname);
1207: }
1208: }
1209: else {
1210: PQreset(le->ptr);
1211: }
1212: if (le->ptr==NULL || PQstatus(le->ptr)==CONNECTION_BAD) {
1213: php_error_docref(NULL TSRMLS_CC, E_WARNING,"PostgreSQL link lost, unable to reconnect");
1214: zend_hash_del(&EG(persistent_list),str.c,str.len+1);
1215: goto err;
1216: }
1217: }
1218: pgsql = (PGconn *) le->ptr;
1219: #if HAVE_PQPROTOCOLVERSION && HAVE_PQPARAMETERSTATUS
1220: if (PQprotocolVersion(pgsql) >= 3 && atof(PQparameterStatus(pgsql, "server_version")) >= 7.2) {
1221: #else
1222: if (atof(PG_VERSION) >= 7.2) {
1223: #endif
1224: pg_result = PQexec(pgsql, "RESET ALL;");
1225: PQclear(pg_result);
1226: }
1227: }
1228: ZEND_REGISTER_RESOURCE(return_value, pgsql, le_plink);
1229: } else { /* Non persistent connection */
1230: zend_rsrc_list_entry *index_ptr,new_index_ptr;
1231:
1232: /* first we check the hash for the hashed_details key. if it exists,
1233: * it should point us to the right offset where the actual pgsql link sits.
1234: * if it doesn't, open a new pgsql link, add it to the resource list,
1235: * and add a pointer to it with hashed_details as the key.
1236: */
1237: if (!(connect_type & PGSQL_CONNECT_FORCE_NEW)
1238: && zend_hash_find(&EG(regular_list),str.c,str.len+1,(void **) &index_ptr)==SUCCESS) {
1239: int type;
1240: ulong link;
1241: void *ptr;
1242:
1243: if (Z_TYPE_P(index_ptr) != le_index_ptr) {
1244: RETURN_FALSE;
1245: }
1246: link = (ulong) index_ptr->ptr;
1247: ptr = zend_list_find(link,&type); /* check if the link is still there */
1248: if (ptr && (type==le_link || type==le_plink)) {
1249: Z_LVAL_P(return_value) = link;
1250: zend_list_addref(link);
1251: php_pgsql_set_default_link(link TSRMLS_CC);
1252: Z_TYPE_P(return_value) = IS_RESOURCE;
1253: goto cleanup;
1254: } else {
1255: zend_hash_del(&EG(regular_list),str.c,str.len+1);
1256: }
1257: }
1258: if (PGG(max_links)!=-1 && PGG(num_links)>=PGG(max_links)) {
1259: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot create new link. Too many open links (%ld)", PGG(num_links));
1260: goto err;
1261: }
1262: if (connstring) {
1263: pgsql = PQconnectdb(connstring);
1264: } else {
1265: pgsql = PQsetdb(host,port,options,tty,dbname);
1266: }
1267: if (pgsql==NULL || PQstatus(pgsql)==CONNECTION_BAD) {
1268: PHP_PQ_ERROR("Unable to connect to PostgreSQL server: %s", pgsql);
1269: if (pgsql) {
1270: PQfinish(pgsql);
1271: }
1272: goto err;
1273: }
1274:
1275: /* add it to the list */
1276: ZEND_REGISTER_RESOURCE(return_value, pgsql, le_link);
1277:
1278: /* add it to the hash */
1279: new_index_ptr.ptr = (void *) Z_LVAL_P(return_value);
1280: Z_TYPE(new_index_ptr) = le_index_ptr;
1281: if (zend_hash_update(&EG(regular_list),str.c,str.len+1,(void *) &new_index_ptr, sizeof(zend_rsrc_list_entry), NULL)==FAILURE) {
1282: goto err;
1283: }
1284: PGG(num_links)++;
1285: }
1286: /* set notice processer */
1287: if (! PGG(ignore_notices) && Z_TYPE_P(return_value) == IS_RESOURCE) {
1288: PQsetNoticeProcessor(pgsql, _php_pgsql_notice_handler, (void*)Z_RESVAL_P(return_value));
1289: }
1290: php_pgsql_set_default_link(Z_LVAL_P(return_value) TSRMLS_CC);
1291:
1292: cleanup:
1293: smart_str_free(&str);
1294: return;
1295:
1296: err:
1297: smart_str_free(&str);
1298: RETURN_FALSE;
1299: }
1300: /* }}} */
1301:
1302: #if 0
1303: /* {{{ php_pgsql_get_default_link
1304: */
1305: static int php_pgsql_get_default_link(INTERNAL_FUNCTION_PARAMETERS)
1306: {
1307: if (PGG(default_link)==-1) { /* no link opened yet, implicitly open one */
1308: ht = 0;
1309: php_pgsql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
1310: }
1311: return PGG(default_link);
1312: }
1313: /* }}} */
1314: #endif
1315:
1316: /* {{{ proto resource pg_connect(string connection_string[, int connect_type] | [string host, string port [, string options [, string tty,]]] string database)
1317: Open a PostgreSQL connection */
1318: PHP_FUNCTION(pg_connect)
1319: {
1320: php_pgsql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
1321: }
1322: /* }}} */
1323:
1324: /* {{{ proto resource pg_pconnect(string connection_string | [string host, string port [, string options [, string tty,]]] string database)
1325: Open a persistent PostgreSQL connection */
1326: PHP_FUNCTION(pg_pconnect)
1327: {
1328: php_pgsql_do_connect(INTERNAL_FUNCTION_PARAM_PASSTHRU,1);
1329: }
1330: /* }}} */
1331:
1332: /* {{{ proto bool pg_close([resource connection])
1333: Close a PostgreSQL connection */
1334: PHP_FUNCTION(pg_close)
1335: {
1336: zval *pgsql_link = NULL;
1337: int id = -1, argc = ZEND_NUM_ARGS();
1338: PGconn *pgsql;
1339:
1340: if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) {
1341: return;
1342: }
1343:
1344: if (argc == 0) {
1345: id = PGG(default_link);
1346: CHECK_DEFAULT_LINK(id);
1347: }
1348:
1349: if (pgsql_link == NULL && id == -1) {
1350: RETURN_FALSE;
1351: }
1352:
1353: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
1354:
1355: if (id==-1) { /* explicit resource number */
1356: zend_list_delete(Z_RESVAL_P(pgsql_link));
1357: }
1358:
1359: if (id!=-1
1360: || (pgsql_link && Z_RESVAL_P(pgsql_link)==PGG(default_link))) {
1361: zend_list_delete(PGG(default_link));
1362: PGG(default_link) = -1;
1363: }
1364:
1365: RETURN_TRUE;
1366: }
1367: /* }}} */
1368:
1369:
1370: #define PHP_PG_DBNAME 1
1371: #define PHP_PG_ERROR_MESSAGE 2
1372: #define PHP_PG_OPTIONS 3
1373: #define PHP_PG_PORT 4
1374: #define PHP_PG_TTY 5
1375: #define PHP_PG_HOST 6
1376: #define PHP_PG_VERSION 7
1377:
1378: /* {{{ php_pgsql_get_link_info
1379: */
1380: static void php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
1381: {
1382: zval *pgsql_link = NULL;
1383: int id = -1, argc = ZEND_NUM_ARGS();
1384: PGconn *pgsql;
1385: char *msgbuf;
1386:
1387: if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) {
1388: return;
1389: }
1390:
1391: if (argc == 0) {
1392: id = PGG(default_link);
1393: CHECK_DEFAULT_LINK(id);
1394: }
1395:
1396: if (pgsql_link == NULL && id == -1) {
1397: RETURN_FALSE;
1398: }
1399:
1400: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
1401:
1402: switch(entry_type) {
1403: case PHP_PG_DBNAME:
1404: Z_STRVAL_P(return_value) = PQdb(pgsql);
1405: break;
1406: case PHP_PG_ERROR_MESSAGE:
1407: RETURN_STRING(PQErrorMessageTrim(pgsql, &msgbuf), 0);
1408: return;
1409: case PHP_PG_OPTIONS:
1410: Z_STRVAL_P(return_value) = PQoptions(pgsql);
1411: break;
1412: case PHP_PG_PORT:
1413: Z_STRVAL_P(return_value) = PQport(pgsql);
1414: break;
1415: case PHP_PG_TTY:
1416: Z_STRVAL_P(return_value) = PQtty(pgsql);
1417: break;
1418: case PHP_PG_HOST:
1419: Z_STRVAL_P(return_value) = PQhost(pgsql);
1420: break;
1421: case PHP_PG_VERSION:
1422: array_init(return_value);
1423: add_assoc_string(return_value, "client", PG_VERSION, 1);
1424: #if HAVE_PQPROTOCOLVERSION
1425: add_assoc_long(return_value, "protocol", PQprotocolVersion(pgsql));
1426: #if HAVE_PQPARAMETERSTATUS
1427: if (PQprotocolVersion(pgsql) >= 3) {
1428: add_assoc_string(return_value, "server", (char*)PQparameterStatus(pgsql, "server_version"), 1);
1429: }
1430: #endif
1431: #endif
1432: return;
1433: default:
1434: RETURN_FALSE;
1435: }
1436: if (Z_STRVAL_P(return_value)) {
1437: Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
1438: Z_STRVAL_P(return_value) = (char *) estrdup(Z_STRVAL_P(return_value));
1439: } else {
1440: Z_STRLEN_P(return_value) = 0;
1441: Z_STRVAL_P(return_value) = (char *) estrdup("");
1442: }
1443: Z_TYPE_P(return_value) = IS_STRING;
1444: }
1445: /* }}} */
1446:
1447: /* {{{ proto string pg_dbname([resource connection])
1448: Get the database name */
1449: PHP_FUNCTION(pg_dbname)
1450: {
1451: php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_DBNAME);
1452: }
1453: /* }}} */
1454:
1455: /* {{{ proto string pg_last_error([resource connection])
1456: Get the error message string */
1457: PHP_FUNCTION(pg_last_error)
1458: {
1459: php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_ERROR_MESSAGE);
1460: }
1461: /* }}} */
1462:
1463: /* {{{ proto string pg_options([resource connection])
1464: Get the options associated with the connection */
1465: PHP_FUNCTION(pg_options)
1466: {
1467: php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_OPTIONS);
1468: }
1469: /* }}} */
1470:
1471: /* {{{ proto int pg_port([resource connection])
1472: Return the port number associated with the connection */
1473: PHP_FUNCTION(pg_port)
1474: {
1475: php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_PORT);
1476: }
1477: /* }}} */
1478:
1479: /* {{{ proto string pg_tty([resource connection])
1480: Return the tty name associated with the connection */
1481: PHP_FUNCTION(pg_tty)
1482: {
1483: php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_TTY);
1484: }
1485: /* }}} */
1486:
1487: /* {{{ proto string pg_host([resource connection])
1488: Returns the host name associated with the connection */
1489: PHP_FUNCTION(pg_host)
1490: {
1491: php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_HOST);
1492: }
1493: /* }}} */
1494:
1495: /* {{{ proto array pg_version([resource connection])
1496: Returns an array with client, protocol and server version (when available) */
1497: PHP_FUNCTION(pg_version)
1498: {
1499: php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_VERSION);
1500: }
1501: /* }}} */
1502:
1503: #if HAVE_PQPARAMETERSTATUS
1504: /* {{{ proto string|false pg_parameter_status([resource connection,] string param_name)
1505: Returns the value of a server parameter */
1506: PHP_FUNCTION(pg_parameter_status)
1507: {
1508: zval *pgsql_link;
1509: int id;
1510: PGconn *pgsql;
1511: char *param;
1512: int len;
1513:
1514: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pgsql_link, ¶m, &len) == SUCCESS) {
1515: id = -1;
1516: } else if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", ¶m, &len) == SUCCESS) {
1517: pgsql_link = NULL;
1518: id = PGG(default_link);
1519: } else {
1520: RETURN_FALSE;
1521: }
1522: if (pgsql_link == NULL && id == -1) {
1523: RETURN_FALSE;
1524: }
1525:
1526: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
1527:
1528: param = (char*)PQparameterStatus(pgsql, param);
1529: if (param) {
1530: RETURN_STRING(param, 1);
1531: } else {
1532: RETURN_FALSE;
1533: }
1534: }
1535: /* }}} */
1536: #endif
1537:
1538: /* {{{ proto bool pg_ping([resource connection])
1539: Ping database. If connection is bad, try to reconnect. */
1540: PHP_FUNCTION(pg_ping)
1541: {
1542: zval *pgsql_link;
1543: int id;
1544: PGconn *pgsql;
1545: PGresult *res;
1546:
1547: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r", &pgsql_link) == SUCCESS) {
1548: id = -1;
1549: } else {
1550: pgsql_link = NULL;
1551: id = PGG(default_link);
1552: }
1553: if (pgsql_link == NULL && id == -1) {
1554: RETURN_FALSE;
1555: }
1556:
1557: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
1558:
1559: /* ping connection */
1560: res = PQexec(pgsql, "SELECT 1;");
1561: PQclear(res);
1562:
1563: /* check status. */
1564: if (PQstatus(pgsql) == CONNECTION_OK)
1565: RETURN_TRUE;
1566:
1567: /* reset connection if it's broken */
1568: PQreset(pgsql);
1569: if (PQstatus(pgsql) == CONNECTION_OK) {
1570: RETURN_TRUE;
1571: }
1572: RETURN_FALSE;
1573: }
1574: /* }}} */
1575:
1576: /* {{{ proto resource pg_query([resource connection,] string query)
1577: Execute a query */
1578: PHP_FUNCTION(pg_query)
1579: {
1580: zval *pgsql_link = NULL;
1581: char *query;
1582: int id = -1, query_len, argc = ZEND_NUM_ARGS();
1583: int leftover = 0;
1584: PGconn *pgsql;
1585: PGresult *pgsql_result;
1586: ExecStatusType status;
1587: pgsql_result_handle *pg_result;
1588:
1589: if (argc == 1) {
1590: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &query, &query_len) == FAILURE) {
1591: return;
1592: }
1593: id = PGG(default_link);
1594: CHECK_DEFAULT_LINK(id);
1595: } else {
1596: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pgsql_link, &query, &query_len) == FAILURE) {
1597: return;
1598: }
1599: }
1600:
1601: if (pgsql_link == NULL && id == -1) {
1602: RETURN_FALSE;
1603: }
1604:
1605: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
1606:
1607: if (PQ_SETNONBLOCKING(pgsql, 0)) {
1608: php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to blocking mode");
1609: RETURN_FALSE;
1610: }
1611: while ((pgsql_result = PQgetResult(pgsql))) {
1612: PQclear(pgsql_result);
1613: leftover = 1;
1614: }
1615: if (leftover) {
1616: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first");
1617: }
1618: pgsql_result = PQexec(pgsql, query);
1619: if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
1620: PQclear(pgsql_result);
1621: PQreset(pgsql);
1622: pgsql_result = PQexec(pgsql, query);
1623: }
1624:
1625: if (pgsql_result) {
1626: status = PQresultStatus(pgsql_result);
1627: } else {
1628: status = (ExecStatusType) PQstatus(pgsql);
1629: }
1630:
1631: switch (status) {
1632: case PGRES_EMPTY_QUERY:
1633: case PGRES_BAD_RESPONSE:
1634: case PGRES_NONFATAL_ERROR:
1635: case PGRES_FATAL_ERROR:
1636: PHP_PQ_ERROR("Query failed: %s", pgsql);
1637: PQclear(pgsql_result);
1638: RETURN_FALSE;
1639: break;
1640: case PGRES_COMMAND_OK: /* successful command that did not return rows */
1641: default:
1642: if (pgsql_result) {
1643: pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle));
1644: pg_result->conn = pgsql;
1645: pg_result->result = pgsql_result;
1646: pg_result->row = 0;
1647: ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result);
1648: } else {
1649: PQclear(pgsql_result);
1650: RETURN_FALSE;
1651: }
1652: break;
1653: }
1654: }
1655: /* }}} */
1656:
1657: #if HAVE_PQEXECPARAMS || HAVE_PQEXECPREPARED || HAVE_PQSENDQUERYPARAMS || HAVE_PQSENDQUERYPREPARED
1658: /* {{{ _php_pgsql_free_params */
1659: static void _php_pgsql_free_params(char **params, int num_params)
1660: {
1661: if (num_params > 0) {
1662: int i;
1663: for (i = 0; i < num_params; i++) {
1664: if (params[i]) {
1665: efree(params[i]);
1666: }
1667: }
1668: efree(params);
1669: }
1670: }
1671: /* }}} */
1672: #endif
1673:
1674: #if HAVE_PQEXECPARAMS
1675: /* {{{ proto resource pg_query_params([resource connection,] string query, array params)
1676: Execute a query */
1677: PHP_FUNCTION(pg_query_params)
1678: {
1679: zval *pgsql_link = NULL;
1680: zval *pv_param_arr, **tmp;
1681: char *query;
1682: int query_len, id = -1, argc = ZEND_NUM_ARGS();
1683: int leftover = 0;
1684: int num_params = 0;
1685: char **params = NULL;
1686: PGconn *pgsql;
1687: PGresult *pgsql_result;
1688: ExecStatusType status;
1689: pgsql_result_handle *pg_result;
1690:
1691: if (argc == 2) {
1692: if (zend_parse_parameters(argc TSRMLS_CC, "sa", &query, &query_len, &pv_param_arr) == FAILURE) {
1693: return;
1694: }
1695: id = PGG(default_link);
1696: CHECK_DEFAULT_LINK(id);
1697: } else {
1698: if (zend_parse_parameters(argc TSRMLS_CC, "rsa", &pgsql_link, &query, &query_len, &pv_param_arr) == FAILURE) {
1699: return;
1700: }
1701: }
1702:
1703: if (pgsql_link == NULL && id == -1) {
1704: RETURN_FALSE;
1705: }
1706:
1707: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
1708:
1709: if (PQ_SETNONBLOCKING(pgsql, 0)) {
1710: php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to blocking mode");
1711: RETURN_FALSE;
1712: }
1713: while ((pgsql_result = PQgetResult(pgsql))) {
1714: PQclear(pgsql_result);
1715: leftover = 1;
1716: }
1717: if (leftover) {
1718: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first");
1719: }
1720:
1721: zend_hash_internal_pointer_reset(Z_ARRVAL_P(pv_param_arr));
1722: num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr));
1723: if (num_params > 0) {
1724: int i = 0;
1725: params = (char **)safe_emalloc(sizeof(char *), num_params, 0);
1726:
1727: for(i = 0; i < num_params; i++) {
1728: if (zend_hash_get_current_data(Z_ARRVAL_P(pv_param_arr), (void **) &tmp) == FAILURE) {
1729: php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error getting parameter");
1730: _php_pgsql_free_params(params, num_params);
1731: RETURN_FALSE;
1732: }
1733:
1734: if (Z_TYPE_PP(tmp) == IS_NULL) {
1735: params[i] = NULL;
1736: } else {
1737: zval tmp_val = **tmp;
1738: zval_copy_ctor(&tmp_val);
1739: convert_to_string(&tmp_val);
1740: if (Z_TYPE(tmp_val) != IS_STRING) {
1741: php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error converting parameter");
1742: zval_dtor(&tmp_val);
1743: _php_pgsql_free_params(params, num_params);
1744: RETURN_FALSE;
1745: }
1746: params[i] = estrndup(Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
1747: zval_dtor(&tmp_val);
1748: }
1749:
1750: zend_hash_move_forward(Z_ARRVAL_P(pv_param_arr));
1751: }
1752: }
1753:
1754: pgsql_result = PQexecParams(pgsql, query, num_params,
1755: NULL, (const char * const *)params, NULL, NULL, 0);
1756: if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
1757: PQclear(pgsql_result);
1758: PQreset(pgsql);
1759: pgsql_result = PQexecParams(pgsql, query, num_params,
1760: NULL, (const char * const *)params, NULL, NULL, 0);
1761: }
1762:
1763: if (pgsql_result) {
1764: status = PQresultStatus(pgsql_result);
1765: } else {
1766: status = (ExecStatusType) PQstatus(pgsql);
1767: }
1768:
1769: _php_pgsql_free_params(params, num_params);
1770:
1771: switch (status) {
1772: case PGRES_EMPTY_QUERY:
1773: case PGRES_BAD_RESPONSE:
1774: case PGRES_NONFATAL_ERROR:
1775: case PGRES_FATAL_ERROR:
1776: PHP_PQ_ERROR("Query failed: %s", pgsql);
1777: PQclear(pgsql_result);
1778: RETURN_FALSE;
1779: break;
1780: case PGRES_COMMAND_OK: /* successful command that did not return rows */
1781: default:
1782: if (pgsql_result) {
1783: pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle));
1784: pg_result->conn = pgsql;
1785: pg_result->result = pgsql_result;
1786: pg_result->row = 0;
1787: ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result);
1788: } else {
1789: PQclear(pgsql_result);
1790: RETURN_FALSE;
1791: }
1792: break;
1793: }
1794: }
1795: /* }}} */
1796: #endif
1797:
1798: #if HAVE_PQPREPARE
1799: /* {{{ proto resource pg_prepare([resource connection,] string stmtname, string query)
1800: Prepare a query for future execution */
1801: PHP_FUNCTION(pg_prepare)
1802: {
1803: zval *pgsql_link = NULL;
1804: char *query, *stmtname;
1805: int query_len, stmtname_len, id = -1, argc = ZEND_NUM_ARGS();
1806: int leftover = 0;
1807: PGconn *pgsql;
1808: PGresult *pgsql_result;
1809: ExecStatusType status;
1810: pgsql_result_handle *pg_result;
1811:
1812: if (argc == 2) {
1813: if (zend_parse_parameters(argc TSRMLS_CC, "ss", &stmtname, &stmtname_len, &query, &query_len) == FAILURE) {
1814: return;
1815: }
1816: id = PGG(default_link);
1817: CHECK_DEFAULT_LINK(id);
1818: } else {
1819: if (zend_parse_parameters(argc TSRMLS_CC, "rss", &pgsql_link, &stmtname, &stmtname_len, &query, &query_len) == FAILURE) {
1820: return;
1821: }
1822: }
1823:
1824: if (pgsql_link == NULL && id == -1) {
1825: RETURN_FALSE;
1826: }
1827:
1828: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
1829:
1830: if (PQ_SETNONBLOCKING(pgsql, 0)) {
1831: php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to blocking mode");
1832: RETURN_FALSE;
1833: }
1834: while ((pgsql_result = PQgetResult(pgsql))) {
1835: PQclear(pgsql_result);
1836: leftover = 1;
1837: }
1838: if (leftover) {
1839: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first");
1840: }
1841: pgsql_result = PQprepare(pgsql, stmtname, query, 0, NULL);
1842: if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
1843: PQclear(pgsql_result);
1844: PQreset(pgsql);
1845: pgsql_result = PQprepare(pgsql, stmtname, query, 0, NULL);
1846: }
1847:
1848: if (pgsql_result) {
1849: status = PQresultStatus(pgsql_result);
1850: } else {
1851: status = (ExecStatusType) PQstatus(pgsql);
1852: }
1853:
1854: switch (status) {
1855: case PGRES_EMPTY_QUERY:
1856: case PGRES_BAD_RESPONSE:
1857: case PGRES_NONFATAL_ERROR:
1858: case PGRES_FATAL_ERROR:
1859: PHP_PQ_ERROR("Query failed: %s", pgsql);
1860: PQclear(pgsql_result);
1861: RETURN_FALSE;
1862: break;
1863: case PGRES_COMMAND_OK: /* successful command that did not return rows */
1864: default:
1865: if (pgsql_result) {
1866: pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle));
1867: pg_result->conn = pgsql;
1868: pg_result->result = pgsql_result;
1869: pg_result->row = 0;
1870: ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result);
1871: } else {
1872: PQclear(pgsql_result);
1873: RETURN_FALSE;
1874: }
1875: break;
1876: }
1877: }
1878: /* }}} */
1879: #endif
1880:
1881: #if HAVE_PQEXECPREPARED
1882: /* {{{ proto resource pg_execute([resource connection,] string stmtname, array params)
1883: Execute a prepared query */
1884: PHP_FUNCTION(pg_execute)
1885: {
1886: zval *pgsql_link = NULL;
1887: zval *pv_param_arr, **tmp;
1888: char *stmtname;
1889: int stmtname_len, id = -1, argc = ZEND_NUM_ARGS();
1890: int leftover = 0;
1891: int num_params = 0;
1892: char **params = NULL;
1893: PGconn *pgsql;
1894: PGresult *pgsql_result;
1895: ExecStatusType status;
1896: pgsql_result_handle *pg_result;
1897:
1898: if (argc == 2) {
1899: if (zend_parse_parameters(argc TSRMLS_CC, "sa/", &stmtname, &stmtname_len, &pv_param_arr)==FAILURE) {
1900: return;
1901: }
1902: id = PGG(default_link);
1903: CHECK_DEFAULT_LINK(id);
1904: } else {
1905: if (zend_parse_parameters(argc TSRMLS_CC, "rsa/", &pgsql_link, &stmtname, &stmtname_len, &pv_param_arr) == FAILURE) {
1906: return;
1907: }
1908: }
1909:
1910: if (pgsql_link == NULL && id == -1) {
1911: RETURN_FALSE;
1912: }
1913:
1914: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
1915:
1916: if (PQ_SETNONBLOCKING(pgsql, 0)) {
1917: php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to blocking mode");
1918: RETURN_FALSE;
1919: }
1920: while ((pgsql_result = PQgetResult(pgsql))) {
1921: PQclear(pgsql_result);
1922: leftover = 1;
1923: }
1924: if (leftover) {
1925: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Found results on this connection. Use pg_get_result() to get these results first");
1926: }
1927:
1928: zend_hash_internal_pointer_reset(Z_ARRVAL_P(pv_param_arr));
1929: num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr));
1930: if (num_params > 0) {
1931: int i = 0;
1932: params = (char **)safe_emalloc(sizeof(char *), num_params, 0);
1933:
1934: for(i = 0; i < num_params; i++) {
1935: if (zend_hash_get_current_data(Z_ARRVAL_P(pv_param_arr), (void **) &tmp) == FAILURE) {
1936: php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error getting parameter");
1937: _php_pgsql_free_params(params, num_params);
1938: RETURN_FALSE;
1939: }
1940:
1941: if (Z_TYPE_PP(tmp) == IS_NULL) {
1942: params[i] = NULL;
1943: } else {
1944: zval tmp_val = **tmp;
1945: zval_copy_ctor(&tmp_val);
1946: convert_to_string(&tmp_val);
1947: if (Z_TYPE(tmp_val) != IS_STRING) {
1948: php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error converting parameter");
1949: zval_dtor(&tmp_val);
1950: _php_pgsql_free_params(params, num_params);
1951: RETURN_FALSE;
1952: }
1953: params[i] = estrndup(Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
1954: zval_dtor(&tmp_val);
1955: }
1956:
1957: zend_hash_move_forward(Z_ARRVAL_P(pv_param_arr));
1958: }
1959: }
1960:
1961: pgsql_result = PQexecPrepared(pgsql, stmtname, num_params,
1962: (const char * const *)params, NULL, NULL, 0);
1963: if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
1964: PQclear(pgsql_result);
1965: PQreset(pgsql);
1966: pgsql_result = PQexecPrepared(pgsql, stmtname, num_params,
1967: (const char * const *)params, NULL, NULL, 0);
1968: }
1969:
1970: if (pgsql_result) {
1971: status = PQresultStatus(pgsql_result);
1972: } else {
1973: status = (ExecStatusType) PQstatus(pgsql);
1974: }
1975:
1976: _php_pgsql_free_params(params, num_params);
1977:
1978: switch (status) {
1979: case PGRES_EMPTY_QUERY:
1980: case PGRES_BAD_RESPONSE:
1981: case PGRES_NONFATAL_ERROR:
1982: case PGRES_FATAL_ERROR:
1983: PHP_PQ_ERROR("Query failed: %s", pgsql);
1984: PQclear(pgsql_result);
1985: RETURN_FALSE;
1986: break;
1987: case PGRES_COMMAND_OK: /* successful command that did not return rows */
1988: default:
1989: if (pgsql_result) {
1990: pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle));
1991: pg_result->conn = pgsql;
1992: pg_result->result = pgsql_result;
1993: pg_result->row = 0;
1994: ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result);
1995: } else {
1996: PQclear(pgsql_result);
1997: RETURN_FALSE;
1998: }
1999: break;
2000: }
2001: }
2002: /* }}} */
2003: #endif
2004:
2005: #define PHP_PG_NUM_ROWS 1
2006: #define PHP_PG_NUM_FIELDS 2
2007: #define PHP_PG_CMD_TUPLES 3
2008:
2009: /* {{{ php_pgsql_get_result_info
2010: */
2011: static void php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
2012: {
2013: zval *result;
2014: PGresult *pgsql_result;
2015: pgsql_result_handle *pg_result;
2016:
2017: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) == FAILURE) {
2018: return;
2019: }
2020:
2021: ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2022:
2023: pgsql_result = pg_result->result;
2024:
2025: switch (entry_type) {
2026: case PHP_PG_NUM_ROWS:
2027: Z_LVAL_P(return_value) = PQntuples(pgsql_result);
2028: break;
2029: case PHP_PG_NUM_FIELDS:
2030: Z_LVAL_P(return_value) = PQnfields(pgsql_result);
2031: break;
2032: case PHP_PG_CMD_TUPLES:
2033: #if HAVE_PQCMDTUPLES
2034: Z_LVAL_P(return_value) = atoi(PQcmdTuples(pgsql_result));
2035: #else
2036: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not supported under this build");
2037: Z_LVAL_P(return_value) = 0;
2038: #endif
2039: break;
2040: default:
2041: RETURN_FALSE;
2042: }
2043: Z_TYPE_P(return_value) = IS_LONG;
2044: }
2045: /* }}} */
2046:
2047: /* {{{ proto int pg_num_rows(resource result)
2048: Return the number of rows in the result */
2049: PHP_FUNCTION(pg_num_rows)
2050: {
2051: php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_NUM_ROWS);
2052: }
2053: /* }}} */
2054:
2055: /* {{{ proto int pg_num_fields(resource result)
2056: Return the number of fields in the result */
2057: PHP_FUNCTION(pg_num_fields)
2058: {
2059: php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_NUM_FIELDS);
2060: }
2061: /* }}} */
2062:
2063: #if HAVE_PQCMDTUPLES
2064: /* {{{ proto int pg_affected_rows(resource result)
2065: Returns the number of affected tuples */
2066: PHP_FUNCTION(pg_affected_rows)
2067: {
2068: php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_CMD_TUPLES);
2069: }
2070: /* }}} */
2071: #endif
2072:
2073: /* {{{ proto string pg_last_notice(resource connection)
2074: Returns the last notice set by the backend */
2075: PHP_FUNCTION(pg_last_notice)
2076: {
2077: zval *pgsql_link;
2078: PGconn *pg_link;
2079: int id = -1;
2080: php_pgsql_notice **notice;
2081:
2082: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pgsql_link) == FAILURE) {
2083: return;
2084: }
2085: /* Just to check if user passed valid resoruce */
2086: ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
2087:
2088: if (zend_hash_index_find(&PGG(notices), Z_RESVAL_P(pgsql_link), (void **)¬ice) == FAILURE) {
2089: RETURN_FALSE;
2090: }
2091: RETURN_STRINGL((*notice)->message, (*notice)->len, 1);
2092: }
2093: /* }}} */
2094:
2095: /* {{{ get_field_name
2096: */
2097: static char *get_field_name(PGconn *pgsql, Oid oid, HashTable *list TSRMLS_DC)
2098: {
2099: PGresult *result;
2100: smart_str str = {0};
2101: zend_rsrc_list_entry *field_type;
2102: char *ret=NULL;
2103:
2104: /* try to lookup the type in the resource list */
2105: smart_str_appends(&str, "pgsql_oid_");
2106: smart_str_append_unsigned(&str, oid);
2107: smart_str_0(&str);
2108:
2109: if (zend_hash_find(list,str.c,str.len+1,(void **) &field_type)==SUCCESS) {
2110: ret = estrdup((char *)field_type->ptr);
2111: } else { /* hash all oid's */
2112: int i,num_rows;
2113: int oid_offset,name_offset;
2114: char *tmp_oid, *end_ptr, *tmp_name;
2115: zend_rsrc_list_entry new_oid_entry;
2116:
2117: if ((result = PQexec(pgsql,"select oid,typname from pg_type")) == NULL || PQresultStatus(result) != PGRES_TUPLES_OK) {
2118: if (result) {
2119: PQclear(result);
2120: }
2121: smart_str_free(&str);
2122: return STR_EMPTY_ALLOC();
2123: }
2124: num_rows = PQntuples(result);
2125: oid_offset = PQfnumber(result,"oid");
2126: name_offset = PQfnumber(result,"typname");
2127:
2128: for (i=0; i<num_rows; i++) {
2129: if ((tmp_oid = PQgetvalue(result,i,oid_offset))==NULL) {
2130: continue;
2131: }
2132:
2133: str.len = 0;
2134: smart_str_appends(&str, "pgsql_oid_");
2135: smart_str_appends(&str, tmp_oid);
2136: smart_str_0(&str);
2137:
2138: if ((tmp_name = PQgetvalue(result,i,name_offset))==NULL) {
2139: continue;
2140: }
2141: Z_TYPE(new_oid_entry) = le_string;
2142: new_oid_entry.ptr = estrdup(tmp_name);
2143: zend_hash_update(list,str.c,str.len+1,(void *) &new_oid_entry, sizeof(zend_rsrc_list_entry), NULL);
2144: if (!ret && strtoul(tmp_oid, &end_ptr, 10)==oid) {
2145: ret = estrdup(tmp_name);
2146: }
2147: }
2148: PQclear(result);
2149: }
2150:
2151: smart_str_free(&str);
2152: return ret;
2153: }
2154: /* }}} */
2155:
2156: #ifdef HAVE_PQFTABLE
2157: /* {{{ proto mixed pg_field_table(resource result, int field_number[, bool oid_only])
2158: Returns the name of the table field belongs to, or table's oid if oid_only is true */
2159: PHP_FUNCTION(pg_field_table)
2160: {
2161: zval *result;
2162: pgsql_result_handle *pg_result;
2163: long fnum = -1;
2164: zend_bool return_oid = 0;
2165: Oid oid;
2166: smart_str hash_key = {0};
2167: char *table_name;
2168: zend_rsrc_list_entry *field_table;
2169:
2170: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|b", &result, &fnum, &return_oid) == FAILURE) {
2171: return;
2172: }
2173:
2174: ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2175:
2176: if (fnum < 0 || fnum >= PQnfields(pg_result->result)) {
2177: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad field offset specified");
2178: RETURN_FALSE;
2179: }
2180:
2181: oid = PQftable(pg_result->result, fnum);
2182:
2183: if (InvalidOid == oid) {
2184: RETURN_FALSE;
2185: }
2186:
2187:
2188: if (return_oid) {
2189: #if UINT_MAX > LONG_MAX /* Oid is unsigned int, we don't need this code, where LONG is wider */
2190: if (oid > LONG_MAX) {
2191: smart_str oidstr = {0};
2192: smart_str_append_unsigned(&oidstr, oid);
2193: smart_str_0(&oidstr);
2194: RETURN_STRINGL(oidstr.c, oidstr.len, 0);
2195: } else
2196: #endif
2197: RETURN_LONG((long)oid);
2198: }
2199:
2200: /* try to lookup the table name in the resource list */
2201: smart_str_appends(&hash_key, "pgsql_table_oid_");
2202: smart_str_append_unsigned(&hash_key, oid);
2203: smart_str_0(&hash_key);
2204:
2205: if (zend_hash_find(&EG(regular_list), hash_key.c, hash_key.len+1, (void **) &field_table) == SUCCESS) {
2206: smart_str_free(&hash_key);
2207: RETURN_STRING((char *)field_table->ptr, 1);
2208: } else { /* Not found, lookup by querying PostgreSQL system tables */
2209: PGresult *tmp_res;
2210: smart_str querystr = {0};
2211: zend_rsrc_list_entry new_field_table;
2212:
2213: smart_str_appends(&querystr, "select relname from pg_class where oid=");
2214: smart_str_append_unsigned(&querystr, oid);
2215: smart_str_0(&querystr);
2216:
2217:
2218: if ((tmp_res = PQexec(pg_result->conn, querystr.c)) == NULL || PQresultStatus(tmp_res) != PGRES_TUPLES_OK) {
2219: if (tmp_res) {
2220: PQclear(tmp_res);
2221: }
2222: smart_str_free(&querystr);
2223: smart_str_free(&hash_key);
2224: RETURN_FALSE;
2225: }
2226:
2227: smart_str_free(&querystr);
2228:
2229: if ((table_name = PQgetvalue(tmp_res, 0, 0)) == NULL) {
2230: PQclear(tmp_res);
2231: smart_str_free(&hash_key);
2232: RETURN_FALSE;
2233: }
2234:
2235: Z_TYPE(new_field_table) = le_string;
2236: new_field_table.ptr = estrdup(table_name);
2237: zend_hash_update(&EG(regular_list), hash_key.c, hash_key.len+1, (void *) &new_field_table, sizeof(zend_rsrc_list_entry), NULL);
2238:
2239: smart_str_free(&hash_key);
2240: PQclear(tmp_res);
2241: RETURN_STRING(table_name, 1);
2242: }
2243:
2244: }
2245: /* }}} */
2246: #endif
2247:
2248: #define PHP_PG_FIELD_NAME 1
2249: #define PHP_PG_FIELD_SIZE 2
2250: #define PHP_PG_FIELD_TYPE 3
2251: #define PHP_PG_FIELD_TYPE_OID 4
2252:
2253: /* {{{ php_pgsql_get_field_info
2254: */
2255: static void php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
2256: {
2257: zval *result;
2258: long field;
2259: PGresult *pgsql_result;
2260: pgsql_result_handle *pg_result;
2261: Oid oid;
2262:
2263: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &result, &field) == FAILURE) {
2264: return;
2265: }
2266:
2267: ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2268:
2269: pgsql_result = pg_result->result;
2270:
2271: if (field < 0 || field >= PQnfields(pgsql_result)) {
2272: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad field offset specified");
2273: RETURN_FALSE;
2274: }
2275:
2276: switch (entry_type) {
2277: case PHP_PG_FIELD_NAME:
2278: Z_STRVAL_P(return_value) = PQfname(pgsql_result, field);
2279: Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
2280: Z_STRVAL_P(return_value) = estrndup(Z_STRVAL_P(return_value),Z_STRLEN_P(return_value));
2281: Z_TYPE_P(return_value) = IS_STRING;
2282: break;
2283: case PHP_PG_FIELD_SIZE:
2284: Z_LVAL_P(return_value) = PQfsize(pgsql_result, field);
2285: Z_TYPE_P(return_value) = IS_LONG;
2286: break;
2287: case PHP_PG_FIELD_TYPE:
2288: Z_STRVAL_P(return_value) = get_field_name(pg_result->conn, PQftype(pgsql_result, field), &EG(regular_list) TSRMLS_CC);
2289: Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
2290: Z_TYPE_P(return_value) = IS_STRING;
2291: break;
2292: case PHP_PG_FIELD_TYPE_OID:
2293:
2294: oid = PQftype(pgsql_result, field);
2295: #if UINT_MAX > LONG_MAX
2296: if (oid > LONG_MAX) {
2297: smart_str s = {0};
2298: smart_str_append_unsigned(&s, oid);
2299: smart_str_0(&s);
2300: Z_STRVAL_P(return_value) = s.c;
2301: Z_STRLEN_P(return_value) = s.len;
2302: Z_TYPE_P(return_value) = IS_STRING;
2303: } else
2304: #endif
2305: {
2306: Z_LVAL_P(return_value) = (long)oid;
2307: Z_TYPE_P(return_value) = IS_LONG;
2308: }
2309: break;
2310: default:
2311: RETURN_FALSE;
2312: }
2313: }
2314: /* }}} */
2315:
2316: /* {{{ proto string pg_field_name(resource result, int field_number)
2317: Returns the name of the field */
2318: PHP_FUNCTION(pg_field_name)
2319: {
2320: php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_FIELD_NAME);
2321: }
2322: /* }}} */
2323:
2324: /* {{{ proto int pg_field_size(resource result, int field_number)
2325: Returns the internal size of the field */
2326: PHP_FUNCTION(pg_field_size)
2327: {
2328: php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_FIELD_SIZE);
2329: }
2330: /* }}} */
2331:
2332: /* {{{ proto string pg_field_type(resource result, int field_number)
2333: Returns the type name for the given field */
2334: PHP_FUNCTION(pg_field_type)
2335: {
2336: php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_FIELD_TYPE);
2337: }
2338: /* }}} */
2339:
2340:
2341: /* {{{ proto string pg_field_type_oid(resource result, int field_number)
2342: Returns the type oid for the given field */
2343: PHP_FUNCTION(pg_field_type_oid)
2344: {
2345: php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_FIELD_TYPE_OID);
2346: }
2347: /* }}} */
2348:
2349: /* {{{ proto int pg_field_num(resource result, string field_name)
2350: Returns the field number of the named field */
2351: PHP_FUNCTION(pg_field_num)
2352: {
2353: zval *result;
2354: char *field;
2355: int field_len;
2356: PGresult *pgsql_result;
2357: pgsql_result_handle *pg_result;
2358:
2359: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &result, &field, &field_len) == FAILURE) {
2360: return;
2361: }
2362:
2363: ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2364:
2365: pgsql_result = pg_result->result;
2366:
2367: Z_LVAL_P(return_value) = PQfnumber(pgsql_result, field);
2368: Z_TYPE_P(return_value) = IS_LONG;
2369: }
2370: /* }}} */
2371:
2372: /* {{{ proto mixed pg_fetch_result(resource result, [int row_number,] mixed field_name)
2373: Returns values from a result identifier */
2374: PHP_FUNCTION(pg_fetch_result)
2375: {
2376: zval *result, **field=NULL;
2377: long row;
2378: PGresult *pgsql_result;
2379: pgsql_result_handle *pg_result;
2380: int field_offset, pgsql_row, argc = ZEND_NUM_ARGS();
2381:
2382: if (argc == 2) {
2383: if (zend_parse_parameters(argc TSRMLS_CC, "rZ", &result, &field) == FAILURE) {
2384: return;
2385: }
2386: } else {
2387: if (zend_parse_parameters(argc TSRMLS_CC, "rlZ", &result, &row, &field) == FAILURE) {
2388: return;
2389: }
2390: }
2391:
2392: ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2393:
2394: pgsql_result = pg_result->result;
2395: if (argc == 2) {
2396: if (pg_result->row < 0) {
2397: pg_result->row = 0;
2398: }
2399: pgsql_row = pg_result->row;
2400: if (pgsql_row >= PQntuples(pgsql_result)) {
2401: RETURN_FALSE;
2402: }
2403: } else {
2404: pgsql_row = row;
2405: if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
2406: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to jump to row %ld on PostgreSQL result index %ld",
2407: row, Z_LVAL_P(result));
2408: RETURN_FALSE;
2409: }
2410: }
2411: switch(Z_TYPE_PP(field)) {
2412: case IS_STRING:
2413: field_offset = PQfnumber(pgsql_result, Z_STRVAL_PP(field));
2414: break;
2415: default:
2416: convert_to_long_ex(field);
2417: field_offset = Z_LVAL_PP(field);
2418: break;
2419: }
2420: if (field_offset<0 || field_offset>=PQnfields(pgsql_result)) {
2421: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset specified");
2422: RETURN_FALSE;
2423: }
2424:
2425: if (PQgetisnull(pgsql_result, pgsql_row, field_offset)) {
2426: Z_TYPE_P(return_value) = IS_NULL;
2427: } else {
2428: char *value = PQgetvalue(pgsql_result, pgsql_row, field_offset);
2429: int value_len = PQgetlength(pgsql_result, pgsql_row, field_offset);
2430: ZVAL_STRINGL(return_value, value, value_len, 1);
2431: }
2432: }
2433: /* }}} */
2434:
2435: /* {{{ void php_pgsql_fetch_hash */
2436: static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, long result_type, int into_object)
2437: {
2438: zval *result, *zrow = NULL;
2439: PGresult *pgsql_result;
2440: pgsql_result_handle *pg_result;
2441: int i, num_fields, pgsql_row, use_row;
2442: long row = -1;
2443: char *field_name;
2444: zval *ctor_params = NULL;
2445: zend_class_entry *ce = NULL;
2446:
2447: if (into_object) {
2448: char *class_name = NULL;
2449: int class_name_len;
2450:
2451: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|z!sz", &result, &zrow, &class_name, &class_name_len, &ctor_params) == FAILURE) {
2452: return;
2453: }
2454: if (!class_name) {
2455: ce = zend_standard_class_def;
2456: } else {
2457: ce = zend_fetch_class(class_name, class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
2458: }
2459: if (!ce) {
2460: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not find class '%s'", class_name);
2461: return;
2462: }
2463: result_type = PGSQL_ASSOC;
2464: } else {
2465: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|z!l", &result, &zrow, &result_type) == FAILURE) {
2466: return;
2467: }
2468: }
2469: if (zrow == NULL) {
2470: row = -1;
2471: } else {
2472: convert_to_long(zrow);
2473: row = Z_LVAL_P(zrow);
2474: if (row < 0) {
2475: php_error_docref(NULL TSRMLS_CC, E_WARNING, "The row parameter must be greater or equal to zero");
2476: RETURN_FALSE;
2477: }
2478: }
2479: use_row = ZEND_NUM_ARGS() > 1 && row != -1;
2480:
2481: if (!(result_type & PGSQL_BOTH)) {
2482: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid result type");
2483: RETURN_FALSE;
2484: }
2485:
2486: ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2487:
2488: pgsql_result = pg_result->result;
2489:
2490: if (use_row) {
2491: pgsql_row = row;
2492: pg_result->row = pgsql_row;
2493: if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
2494: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to jump to row %ld on PostgreSQL result index %ld",
2495: row, Z_LVAL_P(result));
2496: RETURN_FALSE;
2497: }
2498: } else {
2499: /* If 2nd param is NULL, use internal row counter to access next row */
2500: pgsql_row = pg_result->row;
2501: if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
2502: RETURN_FALSE;
2503: }
2504: pg_result->row++;
2505: }
2506:
2507: array_init(return_value);
2508: for (i = 0, num_fields = PQnfields(pgsql_result); i < num_fields; i++) {
2509: if (PQgetisnull(pgsql_result, pgsql_row, i)) {
2510: if (result_type & PGSQL_NUM) {
2511: add_index_null(return_value, i);
2512: }
2513: if (result_type & PGSQL_ASSOC) {
2514: field_name = PQfname(pgsql_result, i);
2515: add_assoc_null(return_value, field_name);
2516: }
2517: } else {
2518: char *element = PQgetvalue(pgsql_result, pgsql_row, i);
2519: if (element) {
2520: char *data;
2521: int data_len;
2522: int should_copy=0;
2523: const uint element_len = strlen(element);
2524:
1.1.1.2 misho 2525: data = safe_estrndup(element, element_len);
2526: data_len = element_len;
1.1 misho 2527:
2528: if (result_type & PGSQL_NUM) {
2529: add_index_stringl(return_value, i, data, data_len, should_copy);
2530: should_copy=1;
2531: }
2532:
2533: if (result_type & PGSQL_ASSOC) {
2534: field_name = PQfname(pgsql_result, i);
2535: add_assoc_stringl(return_value, field_name, data, data_len, should_copy);
2536: }
2537: }
2538: }
2539: }
2540:
2541: if (into_object) {
2542: zval dataset = *return_value;
2543: zend_fcall_info fci;
2544: zend_fcall_info_cache fcc;
2545: zval *retval_ptr;
2546:
2547: object_and_properties_init(return_value, ce, NULL);
2548: zend_merge_properties(return_value, Z_ARRVAL(dataset), 1 TSRMLS_CC);
2549:
2550: if (ce->constructor) {
2551: fci.size = sizeof(fci);
2552: fci.function_table = &ce->function_table;
2553: fci.function_name = NULL;
2554: fci.symbol_table = NULL;
2555: fci.object_ptr = return_value;
2556: fci.retval_ptr_ptr = &retval_ptr;
2557: if (ctor_params && Z_TYPE_P(ctor_params) != IS_NULL) {
2558: if (Z_TYPE_P(ctor_params) == IS_ARRAY) {
2559: HashTable *ht = Z_ARRVAL_P(ctor_params);
2560: Bucket *p;
2561:
2562: fci.param_count = 0;
2563: fci.params = safe_emalloc(sizeof(zval*), ht->nNumOfElements, 0);
2564: p = ht->pListHead;
2565: while (p != NULL) {
2566: fci.params[fci.param_count++] = (zval**)p->pData;
2567: p = p->pListNext;
2568: }
2569: } else {
2570: /* Two problems why we throw exceptions here: PHP is typeless
2571: * and hence passing one argument that's not an array could be
2572: * by mistake and the other way round is possible, too. The
2573: * single value is an array. Also we'd have to make that one
2574: * argument passed by reference.
2575: */
2576: zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Parameter ctor_params must be an array", 0 TSRMLS_CC);
2577: return;
2578: }
2579: } else {
2580: fci.param_count = 0;
2581: fci.params = NULL;
2582: }
2583: fci.no_separation = 1;
2584:
2585: fcc.initialized = 1;
2586: fcc.function_handler = ce->constructor;
2587: fcc.calling_scope = EG(scope);
2588: fcc.called_scope = Z_OBJCE_P(return_value);
2589: fcc.object_ptr = return_value;
2590:
2591: if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
2592: 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);
2593: } else {
2594: if (retval_ptr) {
2595: zval_ptr_dtor(&retval_ptr);
2596: }
2597: }
2598: if (fci.params) {
2599: efree(fci.params);
2600: }
2601: } else if (ctor_params) {
2602: 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);
2603: }
2604: }
2605: }
2606: /* }}} */
2607:
2608: /* {{{ proto array pg_fetch_row(resource result [, int row [, int result_type]])
2609: Get a row as an enumerated array */
2610: PHP_FUNCTION(pg_fetch_row)
2611: {
2612: php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_NUM, 0);
2613: }
2614: /* }}} */
2615:
2616: /* {{{ proto array pg_fetch_assoc(resource result [, int row])
2617: Fetch a row as an assoc array */
2618: PHP_FUNCTION(pg_fetch_assoc)
2619: {
2620: /* pg_fetch_assoc() is added from PHP 4.3.0. It should raise error, when
2621: there is 3rd parameter */
2622: if (ZEND_NUM_ARGS() > 2)
2623: WRONG_PARAM_COUNT;
2624: php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_ASSOC, 0);
2625: }
2626: /* }}} */
2627:
2628: /* {{{ proto array pg_fetch_array(resource result [, int row [, int result_type]])
2629: Fetch a row as an array */
2630: PHP_FUNCTION(pg_fetch_array)
2631: {
2632: php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_BOTH, 0);
2633: }
2634: /* }}} */
2635:
2636: /* {{{ proto object pg_fetch_object(resource result [, int row [, string class_name [, NULL|array ctor_params]]])
2637: Fetch a row as an object */
2638: PHP_FUNCTION(pg_fetch_object)
2639: {
2640: /* pg_fetch_object() allowed result_type used to be. 3rd parameter
2641: must be allowed for compatibility */
2642: php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, PGSQL_ASSOC, 1);
2643: }
2644: /* }}} */
2645:
2646: /* {{{ proto array pg_fetch_all(resource result)
2647: Fetch all rows into array */
2648: PHP_FUNCTION(pg_fetch_all)
2649: {
2650: zval *result;
2651: PGresult *pgsql_result;
2652: pgsql_result_handle *pg_result;
2653:
2654: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) == FAILURE) {
2655: return;
2656: }
2657:
2658: ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2659:
2660: pgsql_result = pg_result->result;
2661: array_init(return_value);
2662: if (php_pgsql_result2array(pgsql_result, return_value TSRMLS_CC) == FAILURE) {
2663: zval_dtor(return_value);
2664: RETURN_FALSE;
2665: }
2666: }
2667: /* }}} */
2668:
2669: /* {{{ proto array pg_fetch_all_columns(resource result [, int column_number])
2670: Fetch all rows into array */
2671: PHP_FUNCTION(pg_fetch_all_columns)
2672: {
2673: zval *result;
2674: PGresult *pgsql_result;
2675: pgsql_result_handle *pg_result;
2676: unsigned long colno=0;
2677: int pg_numrows, pg_row;
2678: size_t num_fields;
2679:
2680: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &result, &colno) == FAILURE) {
2681: RETURN_FALSE;
2682: }
2683:
2684: ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2685:
2686: pgsql_result = pg_result->result;
2687:
2688: num_fields = PQnfields(pgsql_result);
2689: if (colno >= num_fields || colno < 0) {
2690: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid column number '%ld'", colno);
2691: RETURN_FALSE;
2692: }
2693:
2694: array_init(return_value);
2695:
2696: if ((pg_numrows = PQntuples(pgsql_result)) <= 0) {
2697: return;
2698: }
2699:
2700: for (pg_row = 0; pg_row < pg_numrows; pg_row++) {
2701: if (PQgetisnull(pgsql_result, pg_row, colno)) {
2702: add_next_index_null(return_value);
2703: } else {
2704: add_next_index_string(return_value, PQgetvalue(pgsql_result, pg_row, colno), 1);
2705: }
2706: }
2707: }
2708: /* }}} */
2709:
2710: /* {{{ proto bool pg_result_seek(resource result, int offset)
2711: Set internal row offset */
2712: PHP_FUNCTION(pg_result_seek)
2713: {
2714: zval *result;
2715: long row;
2716: pgsql_result_handle *pg_result;
2717:
2718: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &result, &row) == FAILURE) {
2719: return;
2720: }
2721:
2722: ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2723:
2724: if (row < 0 || row >= PQntuples(pg_result->result)) {
2725: RETURN_FALSE;
2726: }
2727:
2728: /* seek to offset */
2729: pg_result->row = row;
2730: RETURN_TRUE;
2731: }
2732: /* }}} */
2733:
2734:
2735: #define PHP_PG_DATA_LENGTH 1
2736: #define PHP_PG_DATA_ISNULL 2
2737:
2738: /* {{{ php_pgsql_data_info
2739: */
2740: static void php_pgsql_data_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
2741: {
2742: zval *result, **field;
2743: long row;
2744: PGresult *pgsql_result;
2745: pgsql_result_handle *pg_result;
2746: int field_offset, pgsql_row, argc = ZEND_NUM_ARGS();
2747:
2748: if (argc == 2) {
2749: if (zend_parse_parameters(argc TSRMLS_CC, "rZ", &result, &field) == FAILURE) {
2750: return;
2751: }
2752: } else {
2753: if (zend_parse_parameters(argc TSRMLS_CC, "rlZ", &result, &row, &field) == FAILURE) {
2754: return;
2755: }
2756: }
2757:
2758: ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2759:
2760: pgsql_result = pg_result->result;
2761: if (argc == 2) {
2762: if (pg_result->row < 0) {
2763: pg_result->row = 0;
2764: }
2765: pgsql_row = pg_result->row;
2766: if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
2767: RETURN_FALSE;
2768: }
2769: } else {
2770: pgsql_row = row;
2771: if (pgsql_row < 0 || pgsql_row >= PQntuples(pgsql_result)) {
2772: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to jump to row %ld on PostgreSQL result index %ld",
2773: row, Z_LVAL_P(result));
2774: RETURN_FALSE;
2775: }
2776: }
2777:
2778: switch(Z_TYPE_PP(field)) {
2779: case IS_STRING:
2780: convert_to_string_ex(field);
2781: field_offset = PQfnumber(pgsql_result, Z_STRVAL_PP(field));
2782: break;
2783: default:
2784: convert_to_long_ex(field);
2785: field_offset = Z_LVAL_PP(field);
2786: break;
2787: }
2788: if (field_offset < 0 || field_offset >= PQnfields(pgsql_result)) {
2789: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad column offset specified");
2790: RETURN_FALSE;
2791: }
2792:
2793: switch (entry_type) {
2794: case PHP_PG_DATA_LENGTH:
2795: Z_LVAL_P(return_value) = PQgetlength(pgsql_result, pgsql_row, field_offset);
2796: break;
2797: case PHP_PG_DATA_ISNULL:
2798: Z_LVAL_P(return_value) = PQgetisnull(pgsql_result, pgsql_row, field_offset);
2799: break;
2800: }
2801: Z_TYPE_P(return_value) = IS_LONG;
2802: }
2803: /* }}} */
2804:
2805: /* {{{ proto int pg_field_prtlen(resource result, [int row,] mixed field_name_or_number)
2806: Returns the printed length */
2807: PHP_FUNCTION(pg_field_prtlen)
2808: {
2809: php_pgsql_data_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_DATA_LENGTH);
2810: }
2811: /* }}} */
2812:
2813: /* {{{ proto int pg_field_is_null(resource result, [int row,] mixed field_name_or_number)
2814: Test if a field is NULL */
2815: PHP_FUNCTION(pg_field_is_null)
2816: {
2817: php_pgsql_data_info(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_DATA_ISNULL);
2818: }
2819: /* }}} */
2820:
2821: /* {{{ proto bool pg_free_result(resource result)
2822: Free result memory */
2823: PHP_FUNCTION(pg_free_result)
2824: {
2825: zval *result;
2826: pgsql_result_handle *pg_result;
2827:
2828: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) == FAILURE) {
2829: return;
2830: }
2831:
2832: ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2833: if (Z_LVAL_P(result) == 0) {
2834: RETURN_FALSE;
2835: }
2836: zend_list_delete(Z_RESVAL_P(result));
2837: RETURN_TRUE;
2838: }
2839: /* }}} */
2840:
2841: /* {{{ proto string pg_last_oid(resource result)
2842: Returns the last object identifier */
2843: PHP_FUNCTION(pg_last_oid)
2844: {
2845: zval *result;
2846: PGresult *pgsql_result;
2847: pgsql_result_handle *pg_result;
2848: #ifdef HAVE_PQOIDVALUE
2849: Oid oid;
2850: #endif
2851:
2852: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) == FAILURE) {
2853: return;
2854: }
2855:
2856: ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
2857: pgsql_result = pg_result->result;
2858: #ifdef HAVE_PQOIDVALUE
2859: oid = PQoidValue(pgsql_result);
2860: if (oid == InvalidOid) {
2861: RETURN_FALSE;
2862: }
2863: PGSQL_RETURN_OID(oid);
2864: #else
2865: Z_STRVAL_P(return_value) = (char *) PQoidStatus(pgsql_result);
2866: if (Z_STRVAL_P(return_value)) {
2867: RETURN_STRING(Z_STRVAL_P(return_value), 1);
2868: }
2869: RETURN_STRING("", 1);
2870: #endif
2871: }
2872: /* }}} */
2873:
2874: /* {{{ proto bool pg_trace(string filename [, string mode [, resource connection]])
2875: Enable tracing a PostgreSQL connection */
2876: PHP_FUNCTION(pg_trace)
2877: {
2878: char *z_filename, *mode = "w";
2879: int z_filename_len, mode_len;
2880: zval *pgsql_link = NULL;
2881: int id = -1, argc = ZEND_NUM_ARGS();
2882: PGconn *pgsql;
2883: FILE *fp = NULL;
2884: php_stream *stream;
2885: id = PGG(default_link);
2886:
2887: if (zend_parse_parameters(argc TSRMLS_CC, "s|sr", &z_filename, &z_filename_len, &mode, &mode_len, &pgsql_link) == FAILURE) {
2888: return;
2889: }
2890:
2891: if (argc < 3) {
2892: CHECK_DEFAULT_LINK(id);
2893: }
2894:
2895: if (pgsql_link == NULL && id == -1) {
2896: RETURN_FALSE;
2897: }
2898:
2899: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
2900:
1.1.1.2 misho 2901: stream = php_stream_open_wrapper(z_filename, mode, REPORT_ERRORS, NULL);
1.1 misho 2902:
2903: if (!stream) {
2904: RETURN_FALSE;
2905: }
2906:
2907: if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void**)&fp, REPORT_ERRORS)) {
2908: php_stream_close(stream);
2909: RETURN_FALSE;
2910: }
2911: php_stream_auto_cleanup(stream);
2912: PQtrace(pgsql, fp);
2913: RETURN_TRUE;
2914: }
2915: /* }}} */
2916:
2917: /* {{{ proto bool pg_untrace([resource connection])
2918: Disable tracing of a PostgreSQL connection */
2919: PHP_FUNCTION(pg_untrace)
2920: {
2921: zval *pgsql_link = NULL;
2922: int id = -1, argc = ZEND_NUM_ARGS();
2923: PGconn *pgsql;
2924:
2925: if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) {
2926: return;
2927: }
2928:
2929: if (argc == 0) {
2930: id = PGG(default_link);
2931: CHECK_DEFAULT_LINK(id);
2932: }
2933:
2934: if (pgsql_link == NULL && id == -1) {
2935: RETURN_FALSE;
2936: }
2937:
2938: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
2939: PQuntrace(pgsql);
2940: RETURN_TRUE;
2941: }
2942: /* }}} */
2943:
2944: /* {{{ proto mixed pg_lo_create([resource connection],[mixed large_object_oid])
2945: Create a large object */
2946: PHP_FUNCTION(pg_lo_create)
2947: {
2948: zval *pgsql_link = NULL, *oid = NULL;
2949: PGconn *pgsql;
2950: Oid pgsql_oid, wanted_oid = InvalidOid;
2951: int id = -1, argc = ZEND_NUM_ARGS();
2952:
2953: if (zend_parse_parameters(argc TSRMLS_CC, "|zz", &pgsql_link, &oid) == FAILURE) {
2954: return;
2955: }
2956:
2957: if ((argc == 1) && (Z_TYPE_P(pgsql_link) != IS_RESOURCE)) {
2958: oid = pgsql_link;
2959: pgsql_link = NULL;
2960: }
2961:
2962: if (pgsql_link == NULL) {
2963: id = PGG(default_link);
2964: CHECK_DEFAULT_LINK(id);
2965: if (id == -1) {
2966: RETURN_FALSE;
2967: }
2968: }
2969:
2970: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
2971:
2972: if (oid) {
2973: #ifndef HAVE_PG_LO_CREATE
2974: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "OID value passing not supported");
2975: #else
2976: switch (Z_TYPE_P(oid)) {
2977: case IS_STRING:
2978: {
2979: char *end_ptr;
2980: wanted_oid = (Oid)strtoul(Z_STRVAL_P(oid), &end_ptr, 10);
2981: if ((Z_STRVAL_P(oid)+Z_STRLEN_P(oid)) != end_ptr) {
2982: /* wrong integer format */
2983: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
2984: RETURN_FALSE;
2985: }
2986: }
2987: break;
2988: case IS_LONG:
2989: if (Z_LVAL_P(oid) < (long)InvalidOid) {
2990: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
2991: RETURN_FALSE;
2992: }
2993: wanted_oid = (Oid)Z_LVAL_P(oid);
2994: break;
2995: default:
2996: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
2997: RETURN_FALSE;
2998: }
2999: if ((pgsql_oid = lo_create(pgsql, wanted_oid)) == InvalidOid) {
3000: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create PostgreSQL large object");
3001: RETURN_FALSE;
3002: }
3003:
3004: PGSQL_RETURN_OID(pgsql_oid);
3005: #endif
3006: }
3007:
3008: if ((pgsql_oid = lo_creat(pgsql, INV_READ|INV_WRITE)) == InvalidOid) {
3009: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create PostgreSQL large object");
3010: RETURN_FALSE;
3011: }
3012:
3013: PGSQL_RETURN_OID(pgsql_oid);
3014: }
3015: /* }}} */
3016:
3017: /* {{{ proto bool pg_lo_unlink([resource connection,] string large_object_oid)
3018: Delete a large object */
3019: PHP_FUNCTION(pg_lo_unlink)
3020: {
3021: zval *pgsql_link = NULL;
3022: long oid_long;
3023: char *oid_string, *end_ptr;
3024: int oid_strlen;
3025: PGconn *pgsql;
3026: Oid oid;
3027: int id = -1;
3028: int argc = ZEND_NUM_ARGS();
3029:
3030: /* accept string type since Oid type is unsigned int */
3031: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3032: "rs", &pgsql_link, &oid_string, &oid_strlen) == SUCCESS) {
3033: oid = (Oid)strtoul(oid_string, &end_ptr, 10);
3034: if ((oid_string+oid_strlen) != end_ptr) {
3035: /* wrong integer format */
3036: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
3037: RETURN_FALSE;
3038: }
3039: }
3040: else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3041: "rl", &pgsql_link, &oid_long) == SUCCESS) {
3042: if (oid_long <= InvalidOid) {
3043: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
3044: RETURN_FALSE;
3045: }
3046: oid = (Oid)oid_long;
3047: }
3048: else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3049: "s", &oid_string, &oid_strlen) == SUCCESS) {
3050: oid = (Oid)strtoul(oid_string, &end_ptr, 10);
3051: if ((oid_string+oid_strlen) != end_ptr) {
3052: /* wrong integer format */
3053: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
3054: RETURN_FALSE;
3055: }
3056: id = PGG(default_link);
3057: CHECK_DEFAULT_LINK(id);
3058: }
3059: else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3060: "l", &oid_long) == SUCCESS) {
3061: if (oid_long <= InvalidOid) {
3062: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID is specified");
3063: RETURN_FALSE;
3064: }
3065: oid = (Oid)oid_long;
3066: id = PGG(default_link);
3067: CHECK_DEFAULT_LINK(id);
3068: }
3069: else {
3070: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Requires 1 or 2 arguments");
3071: RETURN_FALSE;
3072: }
3073: if (pgsql_link == NULL && id == -1) {
3074: RETURN_FALSE;
3075: }
3076:
3077: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3078:
3079: if (lo_unlink(pgsql, oid) == -1) {
3080: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to delete PostgreSQL large object %u", oid);
3081: RETURN_FALSE;
3082: }
3083: RETURN_TRUE;
3084: }
3085: /* }}} */
3086:
3087: /* {{{ proto resource pg_lo_open([resource connection,] int large_object_oid, string mode)
3088: Open a large object and return fd */
3089: PHP_FUNCTION(pg_lo_open)
3090: {
3091: zval *pgsql_link = NULL;
3092: long oid_long;
3093: char *oid_string, *end_ptr, *mode_string;
3094: int oid_strlen, mode_strlen;
3095: PGconn *pgsql;
3096: Oid oid;
3097: int id = -1, pgsql_mode=0, pgsql_lofd;
3098: int create=0;
3099: pgLofp *pgsql_lofp;
3100: int argc = ZEND_NUM_ARGS();
3101:
3102: /* accept string type since Oid is unsigned int */
3103: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3104: "rss", &pgsql_link, &oid_string, &oid_strlen, &mode_string, &mode_strlen) == SUCCESS) {
3105: oid = (Oid)strtoul(oid_string, &end_ptr, 10);
3106: if ((oid_string+oid_strlen) != end_ptr) {
3107: /* wrong integer format */
3108: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
3109: RETURN_FALSE;
3110: }
3111: }
3112: else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3113: "rls", &pgsql_link, &oid_long, &mode_string, &mode_strlen) == SUCCESS) {
3114: if (oid_long <= InvalidOid) {
3115: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
3116: RETURN_FALSE;
3117: }
3118: oid = (Oid)oid_long;
3119: }
3120: else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3121: "ss", &oid_string, &oid_strlen, &mode_string, &mode_strlen) == SUCCESS) {
3122: oid = (Oid)strtoul(oid_string, &end_ptr, 10);
3123: if ((oid_string+oid_strlen) != end_ptr) {
3124: /* wrong integer format */
3125: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
3126: RETURN_FALSE;
3127: }
3128: id = PGG(default_link);
3129: CHECK_DEFAULT_LINK(id);
3130: }
3131: else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3132: "ls", &oid_long, &mode_string, &mode_strlen) == SUCCESS) {
3133: if (oid_long <= InvalidOid) {
3134: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
3135: RETURN_FALSE;
3136: }
3137: oid = (Oid)oid_long;
3138: id = PGG(default_link);
3139: CHECK_DEFAULT_LINK(id);
3140: }
3141: else {
3142: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Requires 1 or 2 arguments");
3143: RETURN_FALSE;
3144: }
3145: if (pgsql_link == NULL && id == -1) {
3146: RETURN_FALSE;
3147: }
3148:
3149: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3150:
3151: /* r/w/+ is little bit more PHP-like than INV_READ/INV_WRITE and a lot of
3152: faster to type. Unfortunately, doesn't behave the same way as fopen()...
3153: (Jouni)
3154: */
3155:
3156: if (strchr(mode_string, 'r') == mode_string) {
3157: pgsql_mode |= INV_READ;
3158: if (strchr(mode_string, '+') == mode_string+1) {
3159: pgsql_mode |= INV_WRITE;
3160: }
3161: }
3162: if (strchr(mode_string, 'w') == mode_string) {
3163: pgsql_mode |= INV_WRITE;
3164: create = 1;
3165: if (strchr(mode_string, '+') == mode_string+1) {
3166: pgsql_mode |= INV_READ;
3167: }
3168: }
3169:
3170: pgsql_lofp = (pgLofp *) emalloc(sizeof(pgLofp));
3171:
3172: if ((pgsql_lofd = lo_open(pgsql, oid, pgsql_mode)) == -1) {
3173: if (create) {
3174: if ((oid = lo_creat(pgsql, INV_READ|INV_WRITE)) == 0) {
3175: efree(pgsql_lofp);
3176: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create PostgreSQL large object");
3177: RETURN_FALSE;
3178: } else {
3179: if ((pgsql_lofd = lo_open(pgsql, oid, pgsql_mode)) == -1) {
3180: if (lo_unlink(pgsql, oid) == -1) {
3181: efree(pgsql_lofp);
3182: 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");
3183: RETURN_FALSE;
3184: }
3185: efree(pgsql_lofp);
3186: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open PostgreSQL large object");
3187: RETURN_FALSE;
3188: } else {
3189: pgsql_lofp->conn = pgsql;
3190: pgsql_lofp->lofd = pgsql_lofd;
1.1.1.2 misho 3191: Z_LVAL_P(return_value) = zend_list_insert(pgsql_lofp, le_lofp TSRMLS_CC);
1.1 misho 3192: Z_TYPE_P(return_value) = IS_LONG;
3193: }
3194: }
3195: } else {
3196: efree(pgsql_lofp);
3197: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to open PostgreSQL large object");
3198: RETURN_FALSE;
3199: }
3200: } else {
3201: pgsql_lofp->conn = pgsql;
3202: pgsql_lofp->lofd = pgsql_lofd;
3203: ZEND_REGISTER_RESOURCE(return_value, pgsql_lofp, le_lofp);
3204: }
3205: }
3206: /* }}} */
3207:
3208: /* {{{ proto bool pg_lo_close(resource large_object)
3209: Close a large object */
3210: PHP_FUNCTION(pg_lo_close)
3211: {
3212: zval *pgsql_lofp;
3213: pgLofp *pgsql;
3214:
3215: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pgsql_lofp) == FAILURE) {
3216: return;
3217: }
3218:
3219: ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_lofp, -1, "PostgreSQL large object", le_lofp);
3220:
3221: if (lo_close((PGconn *)pgsql->conn, pgsql->lofd) < 0) {
3222: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to close PostgreSQL large object descriptor %d", pgsql->lofd);
3223: RETVAL_FALSE;
3224: } else {
3225: RETVAL_TRUE;
3226: }
3227:
3228: zend_list_delete(Z_RESVAL_P(pgsql_lofp));
3229: return;
3230: }
3231: /* }}} */
3232:
3233: #define PGSQL_LO_READ_BUF_SIZE 8192
3234:
3235: /* {{{ proto string pg_lo_read(resource large_object [, int len])
3236: Read a large object */
3237: PHP_FUNCTION(pg_lo_read)
3238: {
3239: zval *pgsql_id;
3240: long len;
3241: int buf_len = PGSQL_LO_READ_BUF_SIZE, nbytes, argc = ZEND_NUM_ARGS();
3242: char *buf;
3243: pgLofp *pgsql;
3244:
3245: if (zend_parse_parameters(argc TSRMLS_CC, "r|l", &pgsql_id, &len) == FAILURE) {
3246: return;
3247: }
3248:
3249: ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_id, -1, "PostgreSQL large object", le_lofp);
3250:
3251: if (argc > 1) {
3252: buf_len = len;
3253: }
3254:
3255: buf = (char *) safe_emalloc(sizeof(char), (buf_len+1), 0);
3256: if ((nbytes = lo_read((PGconn *)pgsql->conn, pgsql->lofd, buf, buf_len))<0) {
3257: efree(buf);
3258: RETURN_FALSE;
3259: }
3260:
3261: buf[nbytes] = '\0';
3262: RETURN_STRINGL(buf, nbytes, 0);
3263: }
3264: /* }}} */
3265:
3266: /* {{{ proto int pg_lo_write(resource large_object, string buf [, int len])
3267: Write a large object */
3268: PHP_FUNCTION(pg_lo_write)
3269: {
3270: zval *pgsql_id;
3271: char *str;
3272: long z_len;
3273: int str_len, nbytes;
3274: int len;
3275: pgLofp *pgsql;
3276: int argc = ZEND_NUM_ARGS();
3277:
3278: if (zend_parse_parameters(argc TSRMLS_CC, "rs|l", &pgsql_id, &str, &str_len, &z_len) == FAILURE) {
3279: return;
3280: }
3281:
3282: if (argc > 2) {
3283: if (z_len > str_len) {
3284: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot write more than buffer size %d. Tried to write %ld", str_len, z_len);
3285: RETURN_FALSE;
3286: }
3287: if (z_len < 0) {
3288: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Buffer size must be larger than 0, but %ld was specified", z_len);
3289: RETURN_FALSE;
3290: }
3291: len = z_len;
3292: }
3293: else {
3294: len = str_len;
3295: }
3296:
3297: ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_id, -1, "PostgreSQL large object", le_lofp);
3298:
3299: if ((nbytes = lo_write((PGconn *)pgsql->conn, pgsql->lofd, str, len)) == -1) {
3300: RETURN_FALSE;
3301: }
3302:
3303: RETURN_LONG(nbytes);
3304: }
3305: /* }}} */
3306:
3307: /* {{{ proto int pg_lo_read_all(resource large_object)
3308: Read a large object and send straight to browser */
3309: PHP_FUNCTION(pg_lo_read_all)
3310: {
3311: zval *pgsql_id;
3312: int tbytes;
3313: volatile int nbytes;
3314: char buf[PGSQL_LO_READ_BUF_SIZE];
3315: pgLofp *pgsql;
3316:
3317: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &pgsql_id) == FAILURE) {
3318: return;
3319: }
3320:
3321: ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_id, -1, "PostgreSQL large object", le_lofp);
3322:
3323: tbytes = 0;
3324: while ((nbytes = lo_read((PGconn *)pgsql->conn, pgsql->lofd, buf, PGSQL_LO_READ_BUF_SIZE))>0) {
3325: PHPWRITE(buf, nbytes);
3326: tbytes += nbytes;
3327: }
3328: RETURN_LONG(tbytes);
3329: }
3330: /* }}} */
3331:
3332: /* {{{ proto int pg_lo_import([resource connection, ] string filename [, mixed oid])
3333: Import large object direct from filesystem */
3334: PHP_FUNCTION(pg_lo_import)
3335: {
3336: zval *pgsql_link = NULL, *oid = NULL;
3337: char *file_in;
3338: int id = -1, name_len;
3339: int argc = ZEND_NUM_ARGS();
3340: PGconn *pgsql;
3341: Oid returned_oid;
3342:
3343: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
1.1.1.2 misho 3344: "rp|z", &pgsql_link, &file_in, &name_len, &oid) == SUCCESS) {
1.1 misho 3345: ;
3346: }
3347: else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
1.1.1.2 misho 3348: "p|z", &file_in, &name_len, &oid) == SUCCESS) {
1.1 misho 3349: id = PGG(default_link);
3350: CHECK_DEFAULT_LINK(id);
3351: }
3352: /* old calling convention, deprecated since PHP 4.2 */
3353: else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
1.1.1.2 misho 3354: "pr", &file_in, &name_len, &pgsql_link ) == SUCCESS) {
1.1 misho 3355: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Old API is used");
3356: }
3357: else {
3358: WRONG_PARAM_COUNT;
3359: }
3360:
3361: if (php_check_open_basedir(file_in TSRMLS_CC)) {
3362: RETURN_FALSE;
3363: }
3364:
3365: if (pgsql_link == NULL && id == -1) {
3366: RETURN_FALSE;
3367: }
3368:
3369: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3370:
3371: if (oid) {
3372: #ifndef HAVE_PG_LO_IMPORT_WITH_OID
3373: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "OID value passing not supported");
3374: #else
3375: Oid wanted_oid;
3376: switch (Z_TYPE_P(oid)) {
3377: case IS_STRING:
3378: {
3379: char *end_ptr;
3380: wanted_oid = (Oid)strtoul(Z_STRVAL_P(oid), &end_ptr, 10);
3381: if ((Z_STRVAL_P(oid)+Z_STRLEN_P(oid)) != end_ptr) {
3382: /* wrong integer format */
3383: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
3384: RETURN_FALSE;
3385: }
3386: }
3387: break;
3388: case IS_LONG:
3389: if (Z_LVAL_P(oid) < (long)InvalidOid) {
3390: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
3391: RETURN_FALSE;
3392: }
3393: wanted_oid = (Oid)Z_LVAL_P(oid);
3394: break;
3395: default:
3396: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "invalid OID value passed");
3397: RETURN_FALSE;
3398: }
3399:
3400: returned_oid = lo_import_with_oid(pgsql, file_in, wanted_oid);
3401:
3402: if (returned_oid == InvalidOid) {
3403: RETURN_FALSE;
3404: }
3405:
3406: PGSQL_RETURN_OID(returned_oid);
3407: #endif
3408: }
3409:
3410: returned_oid = lo_import(pgsql, file_in);
3411:
3412: if (returned_oid == InvalidOid) {
3413: RETURN_FALSE;
3414: }
3415: PGSQL_RETURN_OID(returned_oid);
3416: }
3417: /* }}} */
3418:
3419: /* {{{ proto bool pg_lo_export([resource connection, ] int objoid, string filename)
3420: Export large object direct to filesystem */
3421: PHP_FUNCTION(pg_lo_export)
3422: {
3423: zval *pgsql_link = NULL;
3424: char *file_out, *oid_string, *end_ptr;
3425: int oid_strlen;
3426: int id = -1, name_len;
3427: long oid_long;
3428: Oid oid;
3429: PGconn *pgsql;
3430: int argc = ZEND_NUM_ARGS();
3431:
3432: /* allow string to handle large OID value correctly */
3433: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
1.1.1.2 misho 3434: "rlp", &pgsql_link, &oid_long, &file_out, &name_len) == SUCCESS) {
1.1 misho 3435: if (oid_long <= InvalidOid) {
3436: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
3437: RETURN_FALSE;
3438: }
3439: oid = (Oid)oid_long;
3440: }
3441: else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
3442: "rss", &pgsql_link, &oid_string, &oid_strlen, &file_out, &name_len) == SUCCESS) {
3443: oid = (Oid)strtoul(oid_string, &end_ptr, 10);
3444: if ((oid_string+oid_strlen) != end_ptr) {
3445: /* wrong integer format */
3446: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
3447: RETURN_FALSE;
3448: }
3449: }
3450: else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
1.1.1.2 misho 3451: "lp", &oid_long, &file_out, &name_len) == SUCCESS) {
1.1 misho 3452: if (oid_long <= InvalidOid) {
3453: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
3454: RETURN_FALSE;
3455: }
3456: oid = (Oid)oid_long;
3457: id = PGG(default_link);
3458: CHECK_DEFAULT_LINK(id);
3459: }
3460: else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
1.1.1.2 misho 3461: "sp", &oid_string, &oid_strlen, &file_out, &name_len) == SUCCESS) {
1.1 misho 3462: oid = (Oid)strtoul(oid_string, &end_ptr, 10);
3463: if ((oid_string+oid_strlen) != end_ptr) {
3464: /* wrong integer format */
3465: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
3466: RETURN_FALSE;
3467: }
3468: id = PGG(default_link);
3469: CHECK_DEFAULT_LINK(id);
3470: }
3471: else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
1.1.1.2 misho 3472: "spr", &oid_string, &oid_strlen, &file_out, &name_len, &pgsql_link) == SUCCESS) {
1.1 misho 3473: oid = (Oid)strtoul(oid_string, &end_ptr, 10);
3474: if ((oid_string+oid_strlen) != end_ptr) {
3475: /* wrong integer format */
3476: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Wrong OID value passed");
3477: RETURN_FALSE;
3478: }
3479: }
3480: else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, argc TSRMLS_CC,
1.1.1.2 misho 3481: "lpr", &oid_long, &file_out, &name_len, &pgsql_link) == SUCCESS) {
1.1 misho 3482: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Old API is used");
3483: if (oid_long <= InvalidOid) {
3484: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid OID specified");
3485: RETURN_FALSE;
3486: }
3487: oid = (Oid)oid_long;
3488: }
3489: else {
3490: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Requires 2 or 3 arguments");
3491: RETURN_FALSE;
3492: }
3493:
3494: if (php_check_open_basedir(file_out TSRMLS_CC)) {
3495: RETURN_FALSE;
3496: }
3497:
3498: if (pgsql_link == NULL && id == -1) {
3499: RETURN_FALSE;
3500: }
3501:
3502: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3503:
3504: if (lo_export(pgsql, oid, file_out)) {
3505: RETURN_TRUE;
3506: }
3507: RETURN_FALSE;
3508: }
3509: /* }}} */
3510:
3511: /* {{{ proto bool pg_lo_seek(resource large_object, int offset [, int whence])
3512: Seeks position of large object */
3513: PHP_FUNCTION(pg_lo_seek)
3514: {
3515: zval *pgsql_id = NULL;
3516: long offset = 0, whence = SEEK_CUR;
3517: pgLofp *pgsql;
3518: int argc = ZEND_NUM_ARGS();
3519:
3520: if (zend_parse_parameters(argc TSRMLS_CC, "rl|l", &pgsql_id, &offset, &whence) == FAILURE) {
3521: return;
3522: }
3523: if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) {
3524: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid whence parameter");
3525: return;
3526: }
3527:
3528: ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_id, -1, "PostgreSQL large object", le_lofp);
3529:
3530: if (lo_lseek((PGconn *)pgsql->conn, pgsql->lofd, offset, whence) > -1) {
3531: RETURN_TRUE;
3532: } else {
3533: RETURN_FALSE;
3534: }
3535: }
3536: /* }}} */
3537:
3538: /* {{{ proto int pg_lo_tell(resource large_object)
3539: Returns current position of large object */
3540: PHP_FUNCTION(pg_lo_tell)
3541: {
3542: zval *pgsql_id = NULL;
3543: int offset = 0;
3544: pgLofp *pgsql;
3545: int argc = ZEND_NUM_ARGS();
3546:
3547: if (zend_parse_parameters(argc TSRMLS_CC, "r", &pgsql_id) == FAILURE) {
3548: return;
3549: }
3550:
3551: ZEND_FETCH_RESOURCE(pgsql, pgLofp *, &pgsql_id, -1, "PostgreSQL large object", le_lofp);
3552:
3553: offset = lo_tell((PGconn *)pgsql->conn, pgsql->lofd);
3554: RETURN_LONG(offset);
3555: }
3556: /* }}} */
3557:
3558: #if HAVE_PQSETERRORVERBOSITY
3559: /* {{{ proto int pg_set_error_verbosity([resource connection,] int verbosity)
3560: Set error verbosity */
3561: PHP_FUNCTION(pg_set_error_verbosity)
3562: {
3563: zval *pgsql_link = NULL;
3564: long verbosity;
3565: int id = -1, argc = ZEND_NUM_ARGS();
3566: PGconn *pgsql;
3567:
3568: if (argc == 1) {
3569: if (zend_parse_parameters(argc TSRMLS_CC, "l", &verbosity) == FAILURE) {
3570: return;
3571: }
3572: id = PGG(default_link);
3573: CHECK_DEFAULT_LINK(id);
3574: } else {
3575: if (zend_parse_parameters(argc TSRMLS_CC, "rl", &pgsql_link, &verbosity) == FAILURE) {
3576: return;
3577: }
3578: }
3579:
3580: if (pgsql_link == NULL && id == -1) {
3581: RETURN_FALSE;
3582: }
3583:
3584: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3585:
3586: if (verbosity & (PQERRORS_TERSE|PQERRORS_DEFAULT|PQERRORS_VERBOSE)) {
3587: Z_LVAL_P(return_value) = PQsetErrorVerbosity(pgsql, verbosity);
3588: Z_TYPE_P(return_value) = IS_LONG;
3589: } else {
3590: RETURN_FALSE;
3591: }
3592: }
3593: /* }}} */
3594: #endif
3595:
3596: #ifdef HAVE_PQCLIENTENCODING
3597: /* {{{ proto int pg_set_client_encoding([resource connection,] string encoding)
3598: Set client encoding */
3599: PHP_FUNCTION(pg_set_client_encoding)
3600: {
3601: char *encoding;
3602: int encoding_len;
3603: zval *pgsql_link = NULL;
3604: int id = -1, argc = ZEND_NUM_ARGS();
3605: PGconn *pgsql;
3606:
3607: if (argc == 1) {
3608: if (zend_parse_parameters(argc TSRMLS_CC, "s", &encoding, &encoding_len) == FAILURE) {
3609: return;
3610: }
3611: id = PGG(default_link);
3612: CHECK_DEFAULT_LINK(id);
3613: } else {
3614: if (zend_parse_parameters(argc TSRMLS_CC, "rs", &pgsql_link, &encoding, &encoding_len) == FAILURE) {
3615: return;
3616: }
3617: }
3618:
3619: if (pgsql_link == NULL && id == -1) {
3620: RETURN_FALSE;
3621: }
3622:
3623: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3624:
3625: Z_LVAL_P(return_value) = PQsetClientEncoding(pgsql, encoding);
3626: Z_TYPE_P(return_value) = IS_LONG;
3627: }
3628: /* }}} */
3629:
3630: /* {{{ proto string pg_client_encoding([resource connection])
3631: Get the current client encoding */
3632: PHP_FUNCTION(pg_client_encoding)
3633: {
3634: zval *pgsql_link = NULL;
3635: int id = -1, argc = ZEND_NUM_ARGS();
3636: PGconn *pgsql;
3637:
3638: if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) {
3639: return;
3640: }
3641:
3642: if (argc == 0) {
3643: id = PGG(default_link);
3644: CHECK_DEFAULT_LINK(id);
3645: }
3646:
3647: if (pgsql_link == NULL && id == -1) {
3648: RETURN_FALSE;
3649: }
3650:
3651: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3652:
3653: /* Just do the same as found in PostgreSQL sources... */
3654:
3655: #ifndef HAVE_PGSQL_WITH_MULTIBYTE_SUPPORT
3656: #define pg_encoding_to_char(x) "SQL_ASCII"
3657: #endif
3658:
3659: Z_STRVAL_P(return_value) = (char *) pg_encoding_to_char(PQclientEncoding(pgsql));
3660: Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
3661: Z_STRVAL_P(return_value) = (char *) estrdup(Z_STRVAL_P(return_value));
3662: Z_TYPE_P(return_value) = IS_STRING;
3663: }
3664: /* }}} */
3665: #endif
3666:
3667: #if !HAVE_PQGETCOPYDATA
3668: #define COPYBUFSIZ 8192
3669: #endif
3670:
3671: /* {{{ proto bool pg_end_copy([resource connection])
3672: Sync with backend. Completes the Copy command */
3673: PHP_FUNCTION(pg_end_copy)
3674: {
3675: zval *pgsql_link = NULL;
3676: int id = -1, argc = ZEND_NUM_ARGS();
3677: PGconn *pgsql;
3678: int result = 0;
3679:
3680: if (zend_parse_parameters(argc TSRMLS_CC, "|r", &pgsql_link) == FAILURE) {
3681: return;
3682: }
3683:
3684: if (argc == 0) {
3685: id = PGG(default_link);
3686: CHECK_DEFAULT_LINK(id);
3687: }
3688:
3689: if (pgsql_link == NULL && id == -1) {
3690: RETURN_FALSE;
3691: }
3692:
3693: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3694:
3695: result = PQendcopy(pgsql);
3696:
3697: if (result!=0) {
3698: PHP_PQ_ERROR("Query failed: %s", pgsql);
3699: RETURN_FALSE;
3700: }
3701: RETURN_TRUE;
3702: }
3703: /* }}} */
3704:
3705:
3706: /* {{{ proto bool pg_put_line([resource connection,] string query)
3707: Send null-terminated string to backend server*/
3708: PHP_FUNCTION(pg_put_line)
3709: {
3710: char *query;
3711: zval *pgsql_link = NULL;
3712: int query_len, id = -1;
3713: PGconn *pgsql;
3714: int result = 0, argc = ZEND_NUM_ARGS();
3715:
3716: if (argc == 1) {
3717: if (zend_parse_parameters(argc TSRMLS_CC, "s", &query, &query_len) == FAILURE) {
3718: return;
3719: }
3720: id = PGG(default_link);
3721: CHECK_DEFAULT_LINK(id);
3722: } else {
3723: if (zend_parse_parameters(argc TSRMLS_CC, "rs", &pgsql_link, &query, &query_len) == FAILURE) {
3724: return;
3725: }
3726: }
3727:
3728: if (pgsql_link == NULL && id == -1) {
3729: RETURN_FALSE;
3730: }
3731:
3732: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3733:
3734: result = PQputline(pgsql, query);
3735: if (result==EOF) {
3736: PHP_PQ_ERROR("Query failed: %s", pgsql);
3737: RETURN_FALSE;
3738: }
3739: RETURN_TRUE;
3740: }
3741: /* }}} */
3742:
3743: /* {{{ proto array pg_copy_to(resource connection, string table_name [, string delimiter [, string null_as]])
3744: Copy table to array */
3745: PHP_FUNCTION(pg_copy_to)
3746: {
3747: zval *pgsql_link;
3748: char *table_name, *pg_delim = NULL, *pg_null_as = NULL;
3749: int table_name_len, pg_delim_len, pg_null_as_len, free_pg_null = 0;
3750: char *query;
3751: int id = -1;
3752: PGconn *pgsql;
3753: PGresult *pgsql_result;
3754: ExecStatusType status;
3755: int copydone = 0;
3756: #if !HAVE_PQGETCOPYDATA
3757: char copybuf[COPYBUFSIZ];
3758: #endif
3759: char *csv = (char *)NULL;
3760: int ret;
3761: int argc = ZEND_NUM_ARGS();
3762:
3763: if (zend_parse_parameters(argc TSRMLS_CC, "rs|ss",
3764: &pgsql_link, &table_name, &table_name_len,
3765: &pg_delim, &pg_delim_len, &pg_null_as, &pg_null_as_len) == FAILURE) {
3766: return;
3767: }
3768: if (!pg_delim) {
3769: pg_delim = "\t";
3770: }
3771:
3772: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3773:
3774: if (!pg_null_as) {
3775: pg_null_as = safe_estrdup("\\\\N");
3776: free_pg_null = 1;
3777: }
3778:
3779: spprintf(&query, 0, "COPY %s TO STDOUT DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, *pg_delim, pg_null_as);
3780:
3781: while ((pgsql_result = PQgetResult(pgsql))) {
3782: PQclear(pgsql_result);
3783: }
3784: pgsql_result = PQexec(pgsql, query);
3785: if (free_pg_null) {
3786: efree(pg_null_as);
3787: }
3788: efree(query);
3789:
3790: if (pgsql_result) {
3791: status = PQresultStatus(pgsql_result);
3792: } else {
3793: status = (ExecStatusType) PQstatus(pgsql);
3794: }
3795:
3796: switch (status) {
3797: case PGRES_COPY_OUT:
3798: if (pgsql_result) {
3799: PQclear(pgsql_result);
3800: array_init(return_value);
3801: #if HAVE_PQGETCOPYDATA
3802: while (!copydone)
3803: {
3804: ret = PQgetCopyData(pgsql, &csv, 0);
3805: switch (ret) {
3806: case -1:
3807: copydone = 1;
3808: break;
3809: case 0:
3810: case -2:
3811: PHP_PQ_ERROR("getline failed: %s", pgsql);
3812: RETURN_FALSE;
3813: break;
3814: default:
3815: add_next_index_string(return_value, csv, 1);
3816: PQfreemem(csv);
3817: break;
3818: }
3819: }
3820: #else
3821: while (!copydone)
3822: {
3823: if ((ret = PQgetline(pgsql, copybuf, COPYBUFSIZ))) {
3824: PHP_PQ_ERROR("getline failed: %s", pgsql);
3825: RETURN_FALSE;
3826: }
3827:
3828: if (copybuf[0] == '\\' &&
3829: copybuf[1] == '.' &&
3830: copybuf[2] == '\0')
3831: {
3832: copydone = 1;
3833: }
3834: else
3835: {
3836: if (csv == (char *)NULL) {
3837: csv = estrdup(copybuf);
3838: } else {
3839: csv = (char *)erealloc(csv, strlen(csv) + sizeof(char)*(COPYBUFSIZ+1));
3840: strcat(csv, copybuf);
3841: }
3842:
3843: switch (ret)
3844: {
3845: case EOF:
3846: copydone = 1;
3847: case 0:
3848: add_next_index_string(return_value, csv, 1);
3849: efree(csv);
3850: csv = (char *)NULL;
3851: break;
3852: case 1:
3853: break;
3854: }
3855: }
3856: }
3857: if (PQendcopy(pgsql)) {
3858: PHP_PQ_ERROR("endcopy failed: %s", pgsql);
3859: RETURN_FALSE;
3860: }
3861: #endif
3862: while ((pgsql_result = PQgetResult(pgsql))) {
3863: PQclear(pgsql_result);
3864: }
3865: } else {
3866: PQclear(pgsql_result);
3867: RETURN_FALSE;
3868: }
3869: break;
3870: default:
3871: PQclear(pgsql_result);
3872: PHP_PQ_ERROR("Copy command failed: %s", pgsql);
3873: RETURN_FALSE;
3874: break;
3875: }
3876: }
3877: /* }}} */
3878:
3879: /* {{{ proto bool pg_copy_from(resource connection, string table_name , array rows [, string delimiter [, string null_as]])
3880: Copy table from array */
3881: PHP_FUNCTION(pg_copy_from)
3882: {
3883: zval *pgsql_link = NULL, *pg_rows;
3884: zval **tmp;
3885: char *table_name, *pg_delim = NULL, *pg_null_as = NULL;
3886: int table_name_len, pg_delim_len, pg_null_as_len;
3887: int pg_null_as_free = 0;
3888: char *query;
3889: HashPosition pos;
3890: int id = -1;
3891: PGconn *pgsql;
3892: PGresult *pgsql_result;
3893: ExecStatusType status;
3894: int argc = ZEND_NUM_ARGS();
3895:
3896: if (zend_parse_parameters(argc TSRMLS_CC, "rsa|ss",
3897: &pgsql_link, &table_name, &table_name_len, &pg_rows,
3898: &pg_delim, &pg_delim_len, &pg_null_as, &pg_null_as_len) == FAILURE) {
3899: return;
3900: }
3901: if (!pg_delim) {
3902: pg_delim = "\t";
3903: }
3904: if (!pg_null_as) {
3905: pg_null_as = safe_estrdup("\\\\N");
3906: pg_null_as_free = 1;
3907: }
3908:
3909: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
3910:
3911: spprintf(&query, 0, "COPY %s FROM STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, *pg_delim, pg_null_as);
3912: while ((pgsql_result = PQgetResult(pgsql))) {
3913: PQclear(pgsql_result);
3914: }
3915: pgsql_result = PQexec(pgsql, query);
3916:
3917: if (pg_null_as_free) {
3918: efree(pg_null_as);
3919: }
3920: efree(query);
3921:
3922: if (pgsql_result) {
3923: status = PQresultStatus(pgsql_result);
3924: } else {
3925: status = (ExecStatusType) PQstatus(pgsql);
3926: }
3927:
3928: switch (status) {
3929: case PGRES_COPY_IN:
3930: if (pgsql_result) {
3931: int command_failed = 0;
3932: PQclear(pgsql_result);
3933: zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(pg_rows), &pos);
3934: #if HAVE_PQPUTCOPYDATA
3935: while (zend_hash_get_current_data_ex(Z_ARRVAL_P(pg_rows), (void **) &tmp, &pos) == SUCCESS) {
3936: convert_to_string_ex(tmp);
3937: query = (char *)emalloc(Z_STRLEN_PP(tmp) + 2);
3938: strlcpy(query, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp) + 2);
3939: if(Z_STRLEN_PP(tmp) > 0 && *(query + Z_STRLEN_PP(tmp) - 1) != '\n') {
3940: strlcat(query, "\n", Z_STRLEN_PP(tmp) + 2);
3941: }
3942: if (PQputCopyData(pgsql, query, strlen(query)) != 1) {
3943: efree(query);
3944: PHP_PQ_ERROR("copy failed: %s", pgsql);
3945: RETURN_FALSE;
3946: }
3947: efree(query);
3948: zend_hash_move_forward_ex(Z_ARRVAL_P(pg_rows), &pos);
3949: }
3950: if (PQputCopyEnd(pgsql, NULL) != 1) {
3951: PHP_PQ_ERROR("putcopyend failed: %s", pgsql);
3952: RETURN_FALSE;
3953: }
3954: #else
3955: while (zend_hash_get_current_data_ex(Z_ARRVAL_P(pg_rows), (void **) &tmp, &pos) == SUCCESS) {
3956: convert_to_string_ex(tmp);
3957: query = (char *)emalloc(Z_STRLEN_PP(tmp) + 2);
3958: strlcpy(query, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp) + 2);
3959: if(Z_STRLEN_PP(tmp) > 0 && *(query + Z_STRLEN_PP(tmp) - 1) != '\n') {
3960: strlcat(query, "\n", Z_STRLEN_PP(tmp) + 2);
3961: }
3962: if (PQputline(pgsql, query)==EOF) {
3963: efree(query);
3964: PHP_PQ_ERROR("copy failed: %s", pgsql);
3965: RETURN_FALSE;
3966: }
3967: efree(query);
3968: zend_hash_move_forward_ex(Z_ARRVAL_P(pg_rows), &pos);
3969: }
3970: if (PQputline(pgsql, "\\.\n") == EOF) {
3971: PHP_PQ_ERROR("putline failed: %s", pgsql);
3972: RETURN_FALSE;
3973: }
3974: if (PQendcopy(pgsql)) {
3975: PHP_PQ_ERROR("endcopy failed: %s", pgsql);
3976: RETURN_FALSE;
3977: }
3978: #endif
3979: while ((pgsql_result = PQgetResult(pgsql))) {
3980: if (PGRES_COMMAND_OK != PQresultStatus(pgsql_result)) {
3981: PHP_PQ_ERROR("Copy command failed: %s", pgsql);
3982: command_failed = 1;
3983: }
3984: PQclear(pgsql_result);
3985: }
3986: if (command_failed) {
3987: RETURN_FALSE;
3988: }
3989: } else {
3990: PQclear(pgsql_result);
3991: RETURN_FALSE;
3992: }
3993: RETURN_TRUE;
3994: break;
3995: default:
3996: PQclear(pgsql_result);
3997: PHP_PQ_ERROR("Copy command failed: %s", pgsql);
3998: RETURN_FALSE;
3999: break;
4000: }
4001: }
4002: /* }}} */
4003:
4004: #ifdef HAVE_PQESCAPE
4005: /* {{{ proto string pg_escape_string([resource connection,] string data)
4006: Escape string for text/char type */
4007: PHP_FUNCTION(pg_escape_string)
4008: {
4009: char *from = NULL, *to = NULL;
4010: zval *pgsql_link;
4011: #ifdef HAVE_PQESCAPE_CONN
4012: PGconn *pgsql;
4013: #endif
4014: int to_len;
4015: int from_len;
4016: int id = -1;
4017:
4018: switch (ZEND_NUM_ARGS()) {
4019: case 1:
4020: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &from, &from_len) == FAILURE) {
4021: return;
4022: }
4023: pgsql_link = NULL;
4024: id = PGG(default_link);
4025: break;
4026:
4027: default:
4028: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pgsql_link, &from, &from_len) == FAILURE) {
4029: return;
4030: }
4031: break;
4032: }
4033:
4034: to = (char *) safe_emalloc(from_len, 2, 1);
4035:
4036: #ifdef HAVE_PQESCAPE_CONN
4037: if (pgsql_link != NULL || id != -1) {
4038: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4039: to_len = (int) PQescapeStringConn(pgsql, to, from, (size_t)from_len, NULL);
4040: } else
4041: #endif
4042: to_len = (int) PQescapeString(to, from, (size_t)from_len);
4043:
4044: RETURN_STRINGL(to, to_len, 0);
4045: }
4046: /* }}} */
4047:
4048: /* {{{ proto string pg_escape_bytea([resource connection,] string data)
4049: Escape binary for bytea type */
4050: PHP_FUNCTION(pg_escape_bytea)
4051: {
4052: char *from = NULL, *to = NULL;
4053: size_t to_len;
4054: int from_len, id = -1;
4055: #ifdef HAVE_PQESCAPE_BYTEA_CONN
4056: PGconn *pgsql;
4057: #endif
4058: zval *pgsql_link;
4059:
4060: switch (ZEND_NUM_ARGS()) {
4061: case 1:
4062: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &from, &from_len) == FAILURE) {
4063: return;
4064: }
4065: pgsql_link = NULL;
4066: id = PGG(default_link);
4067: break;
4068:
4069: default:
4070: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pgsql_link, &from, &from_len) == FAILURE) {
4071: return;
4072: }
4073: break;
4074: }
4075:
4076: #ifdef HAVE_PQESCAPE_BYTEA_CONN
4077: if (pgsql_link != NULL || id != -1) {
4078: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4079: to = (char *)PQescapeByteaConn(pgsql, from, (size_t)from_len, &to_len);
4080: } else
4081: #endif
4082: to = (char *)PQescapeBytea((unsigned char*)from, from_len, &to_len);
4083:
4084: RETVAL_STRINGL(to, to_len-1, 1); /* to_len includes addtional '\0' */
4085: PQfreemem(to);
4086: }
4087: /* }}} */
4088:
4089: #if !HAVE_PQUNESCAPEBYTEA
4090: /* PQunescapeBytea() from PostgreSQL 7.3 to provide bytea unescape feature to 7.2 users.
4091: Renamed to php_pgsql_unescape_bytea() */
4092: /*
4093: * PQunescapeBytea - converts the null terminated string representation
4094: * of a bytea, strtext, into binary, filling a buffer. It returns a
4095: * pointer to the buffer which is NULL on error, and the size of the
4096: * buffer in retbuflen. The pointer may subsequently be used as an
4097: * argument to the function free(3). It is the reverse of PQescapeBytea.
4098: *
4099: * The following transformations are reversed:
4100: * '\0' == ASCII 0 == \000
4101: * '\'' == ASCII 39 == \'
4102: * '\\' == ASCII 92 == \\
4103: *
4104: * States:
4105: * 0 normal 0->1->2->3->4
4106: * 1 \ 1->5
4107: * 2 \0 1->6
4108: * 3 \00
4109: * 4 \000
4110: * 5 \'
4111: * 6 \\
4112: */
4113: static unsigned char * php_pgsql_unescape_bytea(unsigned char *strtext, size_t *retbuflen)
4114: {
4115: size_t buflen;
4116: unsigned char *buffer,
4117: *sp,
4118: *bp;
4119: unsigned int state = 0;
4120:
4121: if (strtext == NULL)
4122: return NULL;
4123: buflen = strlen(strtext); /* will shrink, also we discover if
4124: * strtext */
4125: buffer = (unsigned char *) emalloc(buflen); /* isn't NULL terminated */
4126: for (bp = buffer, sp = strtext; *sp != '\0'; bp++, sp++)
4127: {
4128: switch (state)
4129: {
4130: case 0:
4131: if (*sp == '\\')
4132: state = 1;
4133: *bp = *sp;
4134: break;
4135: case 1:
4136: if (*sp == '\'') /* state=5 */
4137: { /* replace \' with 39 */
4138: bp--;
4139: *bp = '\'';
4140: buflen--;
4141: state = 0;
4142: }
4143: else if (*sp == '\\') /* state=6 */
4144: { /* replace \\ with 92 */
4145: bp--;
4146: *bp = '\\';
4147: buflen--;
4148: state = 0;
4149: }
4150: else
4151: {
4152: if (isdigit(*sp))
4153: state = 2;
4154: else
4155: state = 0;
4156: *bp = *sp;
4157: }
4158: break;
4159: case 2:
4160: if (isdigit(*sp))
4161: state = 3;
4162: else
4163: state = 0;
4164: *bp = *sp;
4165: break;
4166: case 3:
4167: if (isdigit(*sp)) /* state=4 */
4168: {
4169: unsigned char *start, *end, buf[4]; /* 000 + '\0' */
4170:
4171: bp -= 3;
4172: memcpy(buf, sp-2, 3);
4173: buf[3] = '\0';
4174: start = buf;
4175: *bp = (unsigned char)strtoul(start, (char **)&end, 8);
4176: buflen -= 3;
4177: state = 0;
4178: }
4179: else
4180: {
4181: *bp = *sp;
4182: state = 0;
4183: }
4184: break;
4185: }
4186: }
4187: buffer = erealloc(buffer, buflen+1);
4188: buffer[buflen] = '\0';
4189:
4190: *retbuflen = buflen;
4191: return buffer;
4192: }
4193: #endif
4194:
4195: /* {{{ proto string pg_unescape_bytea(string data)
4196: Unescape binary for bytea type */
4197: PHP_FUNCTION(pg_unescape_bytea)
4198: {
4199: char *from = NULL, *to = NULL, *tmp = NULL;
4200: size_t to_len;
4201: int from_len;
4202: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
4203: &from, &from_len) == FAILURE) {
4204: return;
4205: }
4206:
4207: #if HAVE_PQUNESCAPEBYTEA
4208: tmp = (char *)PQunescapeBytea((unsigned char*)from, &to_len);
4209: to = estrndup(tmp, to_len);
4210: PQfreemem(tmp);
4211: #else
4212: to = (char *)php_pgsql_unescape_bytea((unsigned char*)from, &to_len);
4213: #endif
4214: if (!to) {
4215: RETURN_FALSE;
4216: }
4217: RETVAL_STRINGL(to, to_len, 0);
4218: }
4219: /* }}} */
4220: #endif
4221:
1.1.1.3 ! misho 4222: #ifdef HAVE_PQESCAPE
! 4223: #if !HAVE_PQESCAPELITERAL
! 4224: /* emulate libpq's PQescapeInternal() 9.0 or later */
! 4225: static char* php_pgsql_PQescapeInternal(PGconn *conn, const char *str, size_t len, int escape_literal) {
! 4226: char *result, *rp;
! 4227: const char *s;
! 4228: size_t tmp_len;
! 4229: int input_len = len;
! 4230: char quote_char = escape_literal ? '\'' : '"';
! 4231:
! 4232: if (!conn) {
! 4233: return NULL;
! 4234: }
! 4235:
! 4236: /*
! 4237: * NOTE: multibyte strings that could cointain slashes should be considered.
! 4238: * (e.g. SJIS, BIG5) However, it cannot be done without valid PGconn and mbstring.
! 4239: * Therefore, this function does not support such encodings currently.
! 4240: * FIXME: add encoding check and skip multibyte char bytes if there is vaild PGconn.
! 4241: */
! 4242:
! 4243: /* allocate enough memory */
! 4244: rp = result = (char *)emalloc(len*2 + 5); /* leading " E" needs extra 2 bytes + quote_chars on both end for 2 bytes + NULL */
! 4245:
! 4246: if (escape_literal) {
! 4247: /* check backslashes */
! 4248: tmp_len = strspn(str, "\\");
! 4249: if (tmp_len != len) {
! 4250: /* add " E" for escaping slashes */
! 4251: *rp++ = ' ';
! 4252: *rp++ = 'E';
! 4253: }
! 4254: }
! 4255: /* open quote */
! 4256: *rp++ = quote_char;
! 4257: for (s = str; s - str < input_len; ++s) {
! 4258: if (*s == quote_char || (escape_literal && *s == '\\')) {
! 4259: *rp++ = *s;
! 4260: *rp++ = *s;
! 4261: } else {
! 4262: *rp++ = *s;
! 4263: }
! 4264: }
! 4265: *rp++ = quote_char;
! 4266: *rp = '\0';
! 4267:
! 4268: return result;
! 4269: }
! 4270: #endif
! 4271:
! 4272: static void php_pgsql_escape_internal(INTERNAL_FUNCTION_PARAMETERS, int escape_literal) {
! 4273: char *from = NULL, *to = NULL, *tmp = NULL;
! 4274: zval *pgsql_link = NULL;
! 4275: PGconn *pgsql;
! 4276: int to_len;
! 4277: int from_len;
! 4278: int id = -1;
! 4279:
! 4280: switch (ZEND_NUM_ARGS()) {
! 4281: case 1:
! 4282: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &from, &from_len) == FAILURE) {
! 4283: return;
! 4284: }
! 4285: pgsql_link = NULL;
! 4286: id = PGG(default_link);
! 4287: break;
! 4288:
! 4289: default:
! 4290: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &pgsql_link, &from, &from_len) == FAILURE) {
! 4291: return;
! 4292: }
! 4293: break;
! 4294: }
! 4295:
! 4296: if (pgsql_link == NULL && id == -1) {
! 4297: RETURN_FALSE;
! 4298: }
! 4299:
! 4300: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
! 4301: if (pgsql == NULL) {
! 4302: php_error_docref(NULL TSRMLS_CC, E_WARNING,"Cannot get default pgsql link");
! 4303: RETURN_FALSE;
! 4304: }
! 4305: #ifdef HAVE_PQESCAPELITERAL
! 4306: if (escape_literal) {
! 4307: tmp = PQescapeLiteral(pgsql, from, (size_t)from_len);
! 4308: } else {
! 4309: tmp = PQescapeIdentifier(pgsql, from, (size_t)from_len);
! 4310: }
! 4311: if (!tmp) {
! 4312: php_error_docref(NULL TSRMLS_CC, E_WARNING,"Failed to escape");
! 4313: RETURN_FALSE;
! 4314: }
! 4315: to = estrdup(tmp);
! 4316: PQfreemem(tmp);
! 4317: #else
! 4318: to = php_pgsql_PQescapeInternal(pgsql, from, (size_t)from_len, escape_literal);
! 4319: if (!to) {
! 4320: php_error_docref(NULL TSRMLS_CC, E_WARNING,"Failed to escape");
! 4321: RETURN_FALSE;
! 4322: }
! 4323: #endif
! 4324:
! 4325: RETURN_STRING(to, 0);
! 4326: }
! 4327:
! 4328: /* {{{ proto string pg_escape_literal([resource connection,] string data)
! 4329: Escape parameter as string literal (i.e. parameter) */
! 4330: PHP_FUNCTION(pg_escape_literal)
! 4331: {
! 4332: php_pgsql_escape_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
! 4333: }
! 4334: /* }}} */
! 4335:
! 4336: /* {{{ proto string pg_escape_identifier([resource connection,] string data)
! 4337: Escape identifier (i.e. table name, field name) */
! 4338: PHP_FUNCTION(pg_escape_identifier)
! 4339: {
! 4340: php_pgsql_escape_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
! 4341: }
! 4342: /* }}} */
! 4343: #endif
! 4344:
! 4345:
1.1 misho 4346: /* {{{ proto string pg_result_error(resource result)
4347: Get error message associated with result */
4348: PHP_FUNCTION(pg_result_error)
4349: {
4350: zval *result;
4351: PGresult *pgsql_result;
4352: pgsql_result_handle *pg_result;
4353: char *err = NULL;
4354:
4355: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
4356: &result) == FAILURE) {
4357: RETURN_FALSE;
4358: }
4359:
4360: ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
4361:
4362: pgsql_result = pg_result->result;
4363: if (!pgsql_result) {
4364: RETURN_FALSE;
4365: }
4366: err = (char *)PQresultErrorMessage(pgsql_result);
4367: RETURN_STRING(err,1);
4368: }
4369: /* }}} */
4370:
4371: #if HAVE_PQRESULTERRORFIELD
4372: /* {{{ proto string pg_result_error_field(resource result, int fieldcode)
4373: Get error message field associated with result */
4374: PHP_FUNCTION(pg_result_error_field)
4375: {
4376: zval *result;
4377: long fieldcode;
4378: PGresult *pgsql_result;
4379: pgsql_result_handle *pg_result;
4380: char *field = NULL;
4381:
4382: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "rl",
4383: &result, &fieldcode) == FAILURE) {
4384: RETURN_FALSE;
4385: }
4386:
4387: ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
4388:
4389: pgsql_result = pg_result->result;
4390: if (!pgsql_result) {
4391: RETURN_FALSE;
4392: }
4393: if (fieldcode & (PG_DIAG_SEVERITY|PG_DIAG_SQLSTATE|PG_DIAG_MESSAGE_PRIMARY|PG_DIAG_MESSAGE_DETAIL
4394: |PG_DIAG_MESSAGE_HINT|PG_DIAG_STATEMENT_POSITION
4395: #if PG_DIAG_INTERNAL_POSITION
4396: |PG_DIAG_INTERNAL_POSITION
4397: #endif
4398: #if PG_DIAG_INTERNAL_QUERY
4399: |PG_DIAG_INTERNAL_QUERY
4400: #endif
4401: |PG_DIAG_CONTEXT|PG_DIAG_SOURCE_FILE|PG_DIAG_SOURCE_LINE
4402: |PG_DIAG_SOURCE_FUNCTION)) {
4403: field = (char *)PQresultErrorField(pgsql_result, fieldcode);
4404: if (field == NULL) {
4405: RETURN_NULL();
4406: } else {
4407: RETURN_STRING(field, 1);
4408: }
4409: } else {
4410: RETURN_FALSE;
4411: }
4412: }
4413: /* }}} */
4414: #endif
4415:
4416: /* {{{ proto int pg_connection_status(resource connection)
4417: Get connection status */
4418: PHP_FUNCTION(pg_connection_status)
4419: {
4420: zval *pgsql_link = NULL;
4421: int id = -1;
4422: PGconn *pgsql;
4423:
4424: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
4425: &pgsql_link) == FAILURE) {
4426: RETURN_FALSE;
4427: }
4428:
4429: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4430:
4431: RETURN_LONG(PQstatus(pgsql));
4432: }
4433:
4434: /* }}} */
4435:
4436: #if HAVE_PGTRANSACTIONSTATUS
4437: /* {{{ proto int pg_transaction_status(resource connection)
4438: Get transaction status */
4439: PHP_FUNCTION(pg_transaction_status)
4440: {
4441: zval *pgsql_link = NULL;
4442: int id = -1;
4443: PGconn *pgsql;
4444:
4445: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
4446: &pgsql_link) == FAILURE) {
4447: RETURN_FALSE;
4448: }
4449:
4450: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4451:
4452: RETURN_LONG(PQtransactionStatus(pgsql));
4453: }
4454: #endif
4455:
4456: /* }}} */
4457:
4458: /* {{{ proto bool pg_connection_reset(resource connection)
4459: Reset connection (reconnect) */
4460: PHP_FUNCTION(pg_connection_reset)
4461: {
4462: zval *pgsql_link;
4463: int id = -1;
4464: PGconn *pgsql;
4465:
4466: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
4467: &pgsql_link) == FAILURE) {
4468: RETURN_FALSE;
4469: }
4470:
4471: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4472:
4473: PQreset(pgsql);
4474: if (PQstatus(pgsql) == CONNECTION_BAD) {
4475: RETURN_FALSE;
4476: }
4477: RETURN_TRUE;
4478: }
4479:
4480: /* }}} */
4481:
4482: #define PHP_PG_ASYNC_IS_BUSY 1
4483: #define PHP_PG_ASYNC_REQUEST_CANCEL 2
4484:
4485: /* {{{ php_pgsql_flush_query
4486: */
4487: static int php_pgsql_flush_query(PGconn *pgsql TSRMLS_DC)
4488: {
4489: PGresult *res;
4490: int leftover = 0;
4491:
4492: if (PQ_SETNONBLOCKING(pgsql, 1)) {
4493: php_error_docref(NULL TSRMLS_CC, E_NOTICE,"Cannot set connection to nonblocking mode");
4494: return -1;
4495: }
4496: while ((res = PQgetResult(pgsql))) {
4497: PQclear(res);
4498: leftover++;
4499: }
4500: PQ_SETNONBLOCKING(pgsql, 0);
4501: return leftover;
4502: }
4503: /* }}} */
4504:
4505: /* {{{ php_pgsql_do_async
4506: */
4507: static void php_pgsql_do_async(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
4508: {
4509: zval *pgsql_link;
4510: int id = -1;
4511: PGconn *pgsql;
4512: PGresult *pgsql_result;
4513:
4514: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
4515: &pgsql_link) == FAILURE) {
4516: RETURN_FALSE;
4517: }
4518:
4519: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4520:
4521: if (PQ_SETNONBLOCKING(pgsql, 1)) {
4522: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to nonblocking mode");
4523: RETURN_FALSE;
4524: }
4525: switch(entry_type) {
4526: case PHP_PG_ASYNC_IS_BUSY:
4527: PQconsumeInput(pgsql);
4528: Z_LVAL_P(return_value) = PQisBusy(pgsql);
4529: Z_TYPE_P(return_value) = IS_LONG;
4530: break;
4531: case PHP_PG_ASYNC_REQUEST_CANCEL:
4532: Z_LVAL_P(return_value) = PQrequestCancel(pgsql);
4533: Z_TYPE_P(return_value) = IS_LONG;
4534: while ((pgsql_result = PQgetResult(pgsql))) {
4535: PQclear(pgsql_result);
4536: }
4537: break;
4538: default:
4539: php_error_docref(NULL TSRMLS_CC, E_ERROR, "PostgreSQL module error, please report this error");
4540: break;
4541: }
4542: if (PQ_SETNONBLOCKING(pgsql, 0)) {
4543: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
4544: }
4545: convert_to_boolean_ex(&return_value);
4546: }
4547: /* }}} */
4548:
4549: /* {{{ proto bool pg_cancel_query(resource connection)
4550: Cancel request */
4551: PHP_FUNCTION(pg_cancel_query)
4552: {
4553: php_pgsql_do_async(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_ASYNC_REQUEST_CANCEL);
4554: }
4555: /* }}} */
4556:
4557: /* {{{ proto bool pg_connection_busy(resource connection)
4558: Get connection is busy or not */
4559: PHP_FUNCTION(pg_connection_busy)
4560: {
4561: php_pgsql_do_async(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_ASYNC_IS_BUSY);
4562: }
4563: /* }}} */
4564:
4565: /* {{{ proto bool pg_send_query(resource connection, string query)
4566: Send asynchronous query */
4567: PHP_FUNCTION(pg_send_query)
4568: {
4569: zval *pgsql_link;
4570: char *query;
4571: int len;
4572: int id = -1;
4573: PGconn *pgsql;
4574: PGresult *res;
4575: int leftover = 0;
4576:
4577: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs",
4578: &pgsql_link, &query, &len) == FAILURE) {
4579: return;
4580: }
4581:
4582: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4583:
4584: if (PQ_SETNONBLOCKING(pgsql, 1)) {
4585: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to nonblocking mode");
4586: RETURN_FALSE;
4587: }
4588: while ((res = PQgetResult(pgsql))) {
4589: PQclear(res);
4590: leftover = 1;
4591: }
4592: if (leftover) {
4593: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "There are results on this connection. Call pg_get_result() until it returns FALSE");
4594: }
4595: if (!PQsendQuery(pgsql, query)) {
4596: if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
4597: PQreset(pgsql);
4598: }
4599: if (!PQsendQuery(pgsql, query)) {
4600: RETURN_FALSE;
4601: }
4602: }
4603: if (PQ_SETNONBLOCKING(pgsql, 0)) {
4604: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
4605: }
4606: RETURN_TRUE;
4607: }
4608: /* }}} */
4609:
4610: #if HAVE_PQSENDQUERYPARAMS
4611: /* {{{ proto bool pg_send_query_params(resource connection, string query, array params)
4612: Send asynchronous parameterized query */
4613: PHP_FUNCTION(pg_send_query_params)
4614: {
4615: zval *pgsql_link, *pv_param_arr, **tmp;
4616: int num_params = 0;
4617: char **params = NULL;
4618: char *query;
4619: int query_len, id = -1;
4620: PGconn *pgsql;
4621: PGresult *res;
4622: int leftover = 0;
4623:
4624: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsa/", &pgsql_link, &query, &query_len, &pv_param_arr) == FAILURE) {
4625: return;
4626: }
4627:
4628: if (pgsql_link == NULL && id == -1) {
4629: RETURN_FALSE;
4630: }
4631:
4632: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4633:
4634: if (PQ_SETNONBLOCKING(pgsql, 1)) {
4635: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to nonblocking mode");
4636: RETURN_FALSE;
4637: }
4638: while ((res = PQgetResult(pgsql))) {
4639: PQclear(res);
4640: leftover = 1;
4641: }
4642: if (leftover) {
4643: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "There are results on this connection. Call pg_get_result() until it returns FALSE");
4644: }
4645:
4646: zend_hash_internal_pointer_reset(Z_ARRVAL_P(pv_param_arr));
4647: num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr));
4648: if (num_params > 0) {
4649: int i = 0;
4650: params = (char **)safe_emalloc(sizeof(char *), num_params, 0);
4651:
4652: for(i = 0; i < num_params; i++) {
4653: if (zend_hash_get_current_data(Z_ARRVAL_P(pv_param_arr), (void **) &tmp) == FAILURE) {
4654: php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error getting parameter");
4655: _php_pgsql_free_params(params, num_params);
4656: RETURN_FALSE;
4657: }
4658:
4659: if (Z_TYPE_PP(tmp) == IS_NULL) {
4660: params[i] = NULL;
4661: } else {
4662: zval tmp_val = **tmp;
4663: zval_copy_ctor(&tmp_val);
4664: convert_to_string(&tmp_val);
4665: if (Z_TYPE(tmp_val) != IS_STRING) {
4666: php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error converting parameter");
4667: zval_dtor(&tmp_val);
4668: _php_pgsql_free_params(params, num_params);
4669: RETURN_FALSE;
4670: }
4671: params[i] = estrndup(Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
4672: zval_dtor(&tmp_val);
4673: }
4674:
4675: zend_hash_move_forward(Z_ARRVAL_P(pv_param_arr));
4676: }
4677: }
4678:
4679: if (!PQsendQueryParams(pgsql, query, num_params, NULL, (const char * const *)params, NULL, NULL, 0)) {
4680: if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
4681: PQreset(pgsql);
4682: }
4683: if (!PQsendQueryParams(pgsql, query, num_params, NULL, (const char * const *)params, NULL, NULL, 0)) {
4684: _php_pgsql_free_params(params, num_params);
4685: RETURN_FALSE;
4686: }
4687: }
4688: _php_pgsql_free_params(params, num_params);
4689: if (PQ_SETNONBLOCKING(pgsql, 0)) {
4690: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
4691: }
4692: RETURN_TRUE;
4693: }
4694: /* }}} */
4695: #endif
4696:
4697: #if HAVE_PQSENDPREPARE
4698: /* {{{ proto bool pg_send_prepare(resource connection, string stmtname, string query)
4699: Asynchronously prepare a query for future execution */
4700: PHP_FUNCTION(pg_send_prepare)
4701: {
4702: zval *pgsql_link;
4703: char *query, *stmtname;
4704: int stmtname_len, query_len, id = -1;
4705: PGconn *pgsql;
4706: PGresult *res;
4707: int leftover = 0;
4708:
4709: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &pgsql_link, &stmtname, &stmtname_len, &query, &query_len) == FAILURE) {
4710: return;
4711: }
4712:
4713: if (pgsql_link == NULL && id == -1) {
4714: RETURN_FALSE;
4715: }
4716:
4717: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4718:
4719: if (PQ_SETNONBLOCKING(pgsql, 1)) {
4720: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to nonblocking mode");
4721: RETURN_FALSE;
4722: }
4723: while ((res = PQgetResult(pgsql))) {
4724: PQclear(res);
4725: leftover = 1;
4726: }
4727: if (leftover) {
4728: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "There are results on this connection. Call pg_get_result() until it returns FALSE");
4729: }
4730: if (!PQsendPrepare(pgsql, stmtname, query, 0, NULL)) {
4731: if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
4732: PQreset(pgsql);
4733: }
4734: if (!PQsendPrepare(pgsql, stmtname, query, 0, NULL)) {
4735: RETURN_FALSE;
4736: }
4737: }
4738: if (PQ_SETNONBLOCKING(pgsql, 0)) {
4739: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
4740: }
4741: RETURN_TRUE;
4742: }
4743: /* }}} */
4744: #endif
4745:
4746: #if HAVE_PQSENDQUERYPREPARED
4747: /* {{{ proto bool pg_send_execute(resource connection, string stmtname, array params)
4748: Executes prevriously prepared stmtname asynchronously */
4749: PHP_FUNCTION(pg_send_execute)
4750: {
4751: zval *pgsql_link;
4752: zval *pv_param_arr, **tmp;
4753: int num_params = 0;
4754: char **params = NULL;
4755: char *stmtname;
4756: int stmtname_len, id = -1;
4757: PGconn *pgsql;
4758: PGresult *res;
4759: int leftover = 0;
4760:
4761: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsa", &pgsql_link, &stmtname, &stmtname_len, &pv_param_arr) == FAILURE) {
4762: return;
4763: }
4764:
4765: if (pgsql_link == NULL && id == -1) {
4766: RETURN_FALSE;
4767: }
4768:
4769: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4770:
4771: if (PQ_SETNONBLOCKING(pgsql, 1)) {
4772: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to nonblocking mode");
4773: RETURN_FALSE;
4774: }
4775: while ((res = PQgetResult(pgsql))) {
4776: PQclear(res);
4777: leftover = 1;
4778: }
4779: if (leftover) {
4780: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "There are results on this connection. Call pg_get_result() until it returns FALSE");
4781: }
4782:
4783: zend_hash_internal_pointer_reset(Z_ARRVAL_P(pv_param_arr));
4784: num_params = zend_hash_num_elements(Z_ARRVAL_P(pv_param_arr));
4785: if (num_params > 0) {
4786: int i = 0;
4787: params = (char **)safe_emalloc(sizeof(char *), num_params, 0);
4788:
4789: for(i = 0; i < num_params; i++) {
4790: if (zend_hash_get_current_data(Z_ARRVAL_P(pv_param_arr), (void **) &tmp) == FAILURE) {
4791: php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error getting parameter");
4792: _php_pgsql_free_params(params, num_params);
4793: RETURN_FALSE;
4794: }
4795:
4796: if (Z_TYPE_PP(tmp) == IS_NULL) {
4797: params[i] = NULL;
4798: } else {
4799: zval tmp_val = **tmp;
4800: zval_copy_ctor(&tmp_val);
4801: convert_to_string(&tmp_val);
4802: if (Z_TYPE(tmp_val) != IS_STRING) {
4803: php_error_docref(NULL TSRMLS_CC, E_WARNING,"Error converting parameter");
4804: zval_dtor(&tmp_val);
4805: _php_pgsql_free_params(params, num_params);
4806: RETURN_FALSE;
4807: }
4808: params[i] = estrndup(Z_STRVAL(tmp_val), Z_STRLEN(tmp_val));
4809: zval_dtor(&tmp_val);
4810: }
4811:
4812: zend_hash_move_forward(Z_ARRVAL_P(pv_param_arr));
4813: }
4814: }
4815:
4816: if (!PQsendQueryPrepared(pgsql, stmtname, num_params, (const char * const *)params, NULL, NULL, 0)) {
4817: if ((PGG(auto_reset_persistent) & 2) && PQstatus(pgsql) != CONNECTION_OK) {
4818: PQreset(pgsql);
4819: }
4820: if (!PQsendQueryPrepared(pgsql, stmtname, num_params, (const char * const *)params, NULL, NULL, 0)) {
4821: _php_pgsql_free_params(params, num_params);
4822: RETURN_FALSE;
4823: }
4824: }
4825: _php_pgsql_free_params(params, num_params);
4826: if (PQ_SETNONBLOCKING(pgsql, 0)) {
4827: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Cannot set connection to blocking mode");
4828: }
4829: RETURN_TRUE;
4830: }
4831: /* }}} */
4832: #endif
4833:
4834: /* {{{ proto resource pg_get_result(resource connection)
4835: Get asynchronous query result */
4836: PHP_FUNCTION(pg_get_result)
4837: {
4838: zval *pgsql_link;
4839: int id = -1;
4840: PGconn *pgsql;
4841: PGresult *pgsql_result;
4842: pgsql_result_handle *pg_result;
4843:
4844: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r", &pgsql_link) == FAILURE) {
4845: RETURN_FALSE;
4846: }
4847:
4848: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4849:
4850: pgsql_result = PQgetResult(pgsql);
4851: if (!pgsql_result) {
4852: /* no result */
4853: RETURN_FALSE;
4854: }
4855: pg_result = (pgsql_result_handle *) emalloc(sizeof(pgsql_result_handle));
4856: pg_result->conn = pgsql;
4857: pg_result->result = pgsql_result;
4858: pg_result->row = 0;
4859: ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result);
4860: }
4861: /* }}} */
4862:
4863: /* {{{ proto mixed pg_result_status(resource result[, long result_type])
4864: Get status of query result */
4865: PHP_FUNCTION(pg_result_status)
4866: {
4867: zval *result;
4868: long result_type = PGSQL_STATUS_LONG;
4869: ExecStatusType status;
4870: PGresult *pgsql_result;
4871: pgsql_result_handle *pg_result;
4872:
4873: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r|l",
4874: &result, &result_type) == FAILURE) {
4875: RETURN_FALSE;
4876: }
4877:
4878: ZEND_FETCH_RESOURCE(pg_result, pgsql_result_handle *, &result, -1, "PostgreSQL result", le_result);
4879:
4880: pgsql_result = pg_result->result;
4881: if (result_type == PGSQL_STATUS_LONG) {
4882: status = PQresultStatus(pgsql_result);
4883: RETURN_LONG((int)status);
4884: }
4885: else if (result_type == PGSQL_STATUS_STRING) {
4886: RETURN_STRING(PQcmdStatus(pgsql_result), 1);
4887: }
4888: else {
4889: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Optional 2nd parameter should be PGSQL_STATUS_LONG or PGSQL_STATUS_STRING");
4890: RETURN_FALSE;
4891: }
4892: }
4893: /* }}} */
4894:
4895:
4896: /* {{{ proto array pg_get_notify([resource connection[, result_type]])
4897: Get asynchronous notification */
4898: PHP_FUNCTION(pg_get_notify)
4899: {
4900: zval *pgsql_link;
4901: int id = -1;
4902: long result_type = PGSQL_ASSOC;
4903: PGconn *pgsql;
4904: PGnotify *pgsql_notify;
4905:
4906: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r|l",
4907: &pgsql_link, &result_type) == FAILURE) {
4908: RETURN_FALSE;
4909: }
4910:
4911: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4912:
4913: if (!(result_type & PGSQL_BOTH)) {
4914: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid result type");
4915: RETURN_FALSE;
4916: }
4917:
4918: PQconsumeInput(pgsql);
4919: pgsql_notify = PQnotifies(pgsql);
4920: if (!pgsql_notify) {
4921: /* no notify message */
4922: RETURN_FALSE;
4923: }
4924: array_init(return_value);
4925: if (result_type & PGSQL_NUM) {
4926: add_index_string(return_value, 0, pgsql_notify->relname, 1);
4927: add_index_long(return_value, 1, pgsql_notify->be_pid);
4928: #if HAVE_PQPROTOCOLVERSION && HAVE_PQPARAMETERSTATUS
4929: if (PQprotocolVersion(pgsql) >= 3 && atof(PQparameterStatus(pgsql, "server_version")) >= 9.0) {
4930: #else
4931: if (atof(PG_VERSION) >= 9.0) {
4932: #endif
1.1.1.3 ! misho 4933: #if HAVE_PQPARAMETERSTATUS
1.1 misho 4934: add_index_string(return_value, 2, pgsql_notify->extra, 1);
1.1.1.3 ! misho 4935: #endif
1.1 misho 4936: }
4937: }
4938: if (result_type & PGSQL_ASSOC) {
4939: add_assoc_string(return_value, "message", pgsql_notify->relname, 1);
4940: add_assoc_long(return_value, "pid", pgsql_notify->be_pid);
4941: #if HAVE_PQPROTOCOLVERSION && HAVE_PQPARAMETERSTATUS
4942: if (PQprotocolVersion(pgsql) >= 3 && atof(PQparameterStatus(pgsql, "server_version")) >= 9.0) {
4943: #else
4944: if (atof(PG_VERSION) >= 9.0) {
4945: #endif
1.1.1.3 ! misho 4946: #if HAVE_PQPARAMETERSTATUS
1.1 misho 4947: add_assoc_string(return_value, "payload", pgsql_notify->extra, 1);
1.1.1.3 ! misho 4948: #endif
1.1 misho 4949: }
4950: }
4951: PQfreemem(pgsql_notify);
4952: }
4953: /* }}} */
4954:
4955: /* {{{ proto int pg_get_pid([resource connection)
4956: Get backend(server) pid */
4957: PHP_FUNCTION(pg_get_pid)
4958: {
4959: zval *pgsql_link;
4960: int id = -1;
4961: PGconn *pgsql;
4962:
4963: if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC, "r",
4964: &pgsql_link) == FAILURE) {
4965: RETURN_FALSE;
4966: }
4967:
4968: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
4969:
4970: RETURN_LONG(PQbackendPID(pgsql));
4971: }
4972: /* }}} */
4973:
4974: /* {{{ php_pgsql_meta_data
4975: * TODO: Add meta_data cache for better performance
4976: */
4977: PHP_PGSQL_API int php_pgsql_meta_data(PGconn *pg_link, const char *table_name, zval *meta TSRMLS_DC)
4978: {
4979: PGresult *pg_result;
4980: char *src, *tmp_name, *tmp_name2 = NULL;
4981: smart_str querystr = {0};
4982: int new_len;
4983: int i, num_rows;
4984: zval *elem;
4985:
4986: if (!*table_name) {
4987: php_error_docref(NULL TSRMLS_CC, E_WARNING, "The table name must be specified");
4988: return FAILURE;
4989: }
4990:
4991: src = estrdup(table_name);
4992: tmp_name = php_strtok_r(src, ".", &tmp_name2);
4993:
4994: if (!tmp_name2 || !*tmp_name2) {
4995: /* Default schema */
4996: tmp_name2 = tmp_name;
4997: tmp_name = "public";
4998: }
4999:
5000: smart_str_appends(&querystr,
1.1.1.3 ! misho 5001: "SELECT a.attname, a.attnum, t.typname, a.attlen, a.attnotnull, a.atthasdef, a.attndims, t.typtype = 'e' "
1.1 misho 5002: "FROM pg_class as c, pg_attribute a, pg_type t, pg_namespace n "
5003: "WHERE a.attnum > 0 AND a.attrelid = c.oid AND c.relname = '");
5004: tmp_name2 = php_addslashes(tmp_name2, strlen(tmp_name2), &new_len, 0 TSRMLS_CC);
5005: smart_str_appendl(&querystr, tmp_name2, new_len);
5006:
5007: smart_str_appends(&querystr, "' AND c.relnamespace = n.oid AND n.nspname = '");
5008: tmp_name = php_addslashes(tmp_name, strlen(tmp_name), &new_len, 0 TSRMLS_CC);
5009: smart_str_appendl(&querystr, tmp_name, new_len);
5010:
5011: smart_str_appends(&querystr, "' AND a.atttypid = t.oid ORDER BY a.attnum;");
5012: smart_str_0(&querystr);
5013:
5014: efree(tmp_name2);
5015: efree(tmp_name);
5016: efree(src);
5017:
5018: pg_result = PQexec(pg_link, querystr.c);
5019: if (PQresultStatus(pg_result) != PGRES_TUPLES_OK || (num_rows = PQntuples(pg_result)) == 0) {
5020: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Table '%s' doesn't exists", table_name);
5021: smart_str_free(&querystr);
5022: PQclear(pg_result);
5023: return FAILURE;
5024: }
5025: smart_str_free(&querystr);
5026:
5027: for (i = 0; i < num_rows; i++) {
5028: char *name;
5029: MAKE_STD_ZVAL(elem);
5030: array_init(elem);
5031: add_assoc_long(elem, "num", atoi(PQgetvalue(pg_result,i,1)));
5032: add_assoc_string(elem, "type", PQgetvalue(pg_result,i,2), 1);
5033: add_assoc_long(elem, "len", atoi(PQgetvalue(pg_result,i,3)));
5034: if (!strcmp(PQgetvalue(pg_result,i,4), "t")) {
5035: add_assoc_bool(elem, "not null", 1);
5036: }
5037: else {
5038: add_assoc_bool(elem, "not null", 0);
5039: }
5040: if (!strcmp(PQgetvalue(pg_result,i,5), "t")) {
5041: add_assoc_bool(elem, "has default", 1);
5042: }
5043: else {
5044: add_assoc_bool(elem, "has default", 0);
5045: }
5046: add_assoc_long(elem, "array dims", atoi(PQgetvalue(pg_result,i,6)));
1.1.1.3 ! misho 5047: if (!strcmp(PQgetvalue(pg_result,i,7), "t")) {
! 5048: add_assoc_bool(elem, "is enum", 1);
! 5049: }
! 5050: else {
! 5051: add_assoc_bool(elem, "is enum", 0);
! 5052: }
1.1 misho 5053: name = PQgetvalue(pg_result,i,0);
5054: add_assoc_zval(meta, name, elem);
5055: }
5056: PQclear(pg_result);
5057:
5058: return SUCCESS;
5059: }
5060:
5061: /* }}} */
5062:
5063:
5064: /* {{{ proto array pg_meta_data(resource db, string table)
5065: Get meta_data */
5066: PHP_FUNCTION(pg_meta_data)
5067: {
5068: zval *pgsql_link;
5069: char *table_name;
5070: uint table_name_len;
5071: PGconn *pgsql;
5072: int id = -1;
5073:
5074: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs",
5075: &pgsql_link, &table_name, &table_name_len) == FAILURE) {
5076: return;
5077: }
5078:
5079: ZEND_FETCH_RESOURCE2(pgsql, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
5080:
5081: array_init(return_value);
5082: if (php_pgsql_meta_data(pgsql, table_name, return_value TSRMLS_CC) == FAILURE) {
5083: zval_dtor(return_value); /* destroy array */
5084: RETURN_FALSE;
5085: }
1.1.1.3 ! misho 5086: else {
! 5087: HashPosition pos;
! 5088: zval **val;
! 5089:
! 5090: for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(return_value), &pos);
! 5091: zend_hash_get_current_data_ex(Z_ARRVAL_P(return_value), (void **)&val, &pos) == SUCCESS;
! 5092: zend_hash_move_forward_ex(Z_ARRVAL_P(return_value), &pos)) {
! 5093: /* delete newly added entry, in order to keep BC */
! 5094: zend_hash_del_key_or_index(Z_ARRVAL_PP(val), "is enum", sizeof("is enum"), 0, HASH_DEL_KEY);
! 5095: }
! 5096: }
! 5097: }
1.1 misho 5098: /* }}} */
5099:
5100: /* {{{ php_pgsql_get_data_type
5101: */
5102: static php_pgsql_data_type php_pgsql_get_data_type(const char *type_name, size_t len)
5103: {
5104: /* This is stupid way to do. I'll fix it when I decied how to support
5105: user defined types. (Yasuo) */
5106:
5107: /* boolean */
5108: if (!strcmp(type_name, "bool")|| !strcmp(type_name, "boolean"))
5109: return PG_BOOL;
5110: /* object id */
5111: if (!strcmp(type_name, "oid"))
5112: return PG_OID;
5113: /* integer */
5114: if (!strcmp(type_name, "int2") || !strcmp(type_name, "smallint"))
5115: return PG_INT2;
5116: if (!strcmp(type_name, "int4") || !strcmp(type_name, "integer"))
5117: return PG_INT4;
5118: if (!strcmp(type_name, "int8") || !strcmp(type_name, "bigint"))
5119: return PG_INT8;
5120: /* real and other */
5121: if (!strcmp(type_name, "float4") || !strcmp(type_name, "real"))
5122: return PG_FLOAT4;
5123: if (!strcmp(type_name, "float8") || !strcmp(type_name, "double precision"))
5124: return PG_FLOAT8;
5125: if (!strcmp(type_name, "numeric"))
5126: return PG_NUMERIC;
5127: if (!strcmp(type_name, "money"))
5128: return PG_MONEY;
5129: /* character */
5130: if (!strcmp(type_name, "text"))
5131: return PG_TEXT;
5132: if (!strcmp(type_name, "bpchar") || !strcmp(type_name, "character"))
5133: return PG_CHAR;
5134: if (!strcmp(type_name, "varchar") || !strcmp(type_name, "character varying"))
5135: return PG_VARCHAR;
5136: /* time and interval */
5137: if (!strcmp(type_name, "abstime"))
5138: return PG_UNIX_TIME;
5139: if (!strcmp(type_name, "reltime"))
5140: return PG_UNIX_TIME_INTERVAL;
5141: if (!strcmp(type_name, "tinterval"))
5142: return PG_UNIX_TIME_INTERVAL;
5143: if (!strcmp(type_name, "date"))
5144: return PG_DATE;
5145: if (!strcmp(type_name, "time"))
5146: return PG_TIME;
5147: if (!strcmp(type_name, "time with time zone") || !strcmp(type_name, "timetz"))
5148: return PG_TIME_WITH_TIMEZONE;
5149: if (!strcmp(type_name, "timestamp without time zone") || !strcmp(type_name, "timestamp"))
5150: return PG_TIMESTAMP;
5151: if (!strcmp(type_name, "timestamp with time zone") || !strcmp(type_name, "timestamptz"))
5152: return PG_TIMESTAMP_WITH_TIMEZONE;
5153: if (!strcmp(type_name, "interval"))
5154: return PG_INTERVAL;
5155: /* binary */
5156: if (!strcmp(type_name, "bytea"))
5157: return PG_BYTEA;
5158: /* network */
5159: if (!strcmp(type_name, "cidr"))
5160: return PG_CIDR;
5161: if (!strcmp(type_name, "inet"))
5162: return PG_INET;
5163: if (!strcmp(type_name, "macaddr"))
5164: return PG_MACADDR;
5165: /* bit */
5166: if (!strcmp(type_name, "bit"))
5167: return PG_BIT;
5168: if (!strcmp(type_name, "bit varying"))
5169: return PG_VARBIT;
5170: /* geometric */
5171: if (!strcmp(type_name, "line"))
5172: return PG_LINE;
5173: if (!strcmp(type_name, "lseg"))
5174: return PG_LSEG;
5175: if (!strcmp(type_name, "box"))
5176: return PG_BOX;
5177: if (!strcmp(type_name, "path"))
5178: return PG_PATH;
5179: if (!strcmp(type_name, "point"))
5180: return PG_POINT;
5181: if (!strcmp(type_name, "polygon"))
5182: return PG_POLYGON;
5183: if (!strcmp(type_name, "circle"))
5184: return PG_CIRCLE;
5185:
5186: return PG_UNKNOWN;
5187: }
5188: /* }}} */
5189:
5190: /* {{{ php_pgsql_convert_match
5191: * test field value with regular expression specified.
5192: */
5193: static int php_pgsql_convert_match(const char *str, const char *regex , int icase TSRMLS_DC)
5194: {
5195: regex_t re;
5196: regmatch_t *subs;
5197: int regopt = REG_EXTENDED;
5198: int regerr, ret = SUCCESS;
5199:
5200: if (icase) {
5201: regopt |= REG_ICASE;
5202: }
5203:
5204: regerr = regcomp(&re, regex, regopt);
5205: if (regerr) {
5206: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot compile regex");
5207: regfree(&re);
5208: return FAILURE;
5209: }
5210: subs = (regmatch_t *)ecalloc(sizeof(regmatch_t), re.re_nsub+1);
5211:
5212: regerr = regexec(&re, str, re.re_nsub+1, subs, 0);
5213: if (regerr == REG_NOMATCH) {
5214: #ifdef PHP_DEBUG
5215: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "'%s' does not match with '%s'", str, regex);
5216: #endif
5217: ret = FAILURE;
5218: }
5219: else if (regerr) {
5220: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot exec regex");
5221: ret = FAILURE;
5222: }
5223: regfree(&re);
5224: efree(subs);
5225: return ret;
5226: }
5227:
5228: /* }}} */
5229:
5230: /* {{{ php_pgsql_add_quote
5231: * add quotes around string.
5232: */
5233: static int php_pgsql_add_quotes(zval *src, zend_bool should_free TSRMLS_DC)
5234: {
5235: smart_str str = {0};
5236:
5237: assert(Z_TYPE_P(src) == IS_STRING);
5238: assert(should_free == 1 || should_free == 0);
5239:
5240: smart_str_appendc(&str, '\'');
5241: smart_str_appendl(&str, Z_STRVAL_P(src), Z_STRLEN_P(src));
5242: smart_str_appendc(&str, '\'');
5243: smart_str_0(&str);
5244:
5245: if (should_free) {
5246: efree(Z_STRVAL_P(src));
5247: }
5248: Z_STRVAL_P(src) = str.c;
5249: Z_STRLEN_P(src) = str.len;
5250:
5251: return SUCCESS;
5252: }
5253: /* }}} */
5254:
5255: #define PGSQL_CONV_CHECK_IGNORE() \
5256: if (!err && Z_TYPE_P(new_val) == IS_STRING && !strcmp(Z_STRVAL_P(new_val), "NULL")) { \
5257: /* if new_value is string "NULL" and field has default value, remove element to use default value */ \
5258: if (!(opt & PGSQL_CONV_IGNORE_DEFAULT) && Z_BVAL_PP(has_default)) { \
5259: zval_dtor(new_val); \
5260: FREE_ZVAL(new_val); \
5261: skip_field = 1; \
5262: } \
5263: /* raise error if it's not null and cannot be ignored */ \
5264: else if (!(opt & PGSQL_CONV_IGNORE_NOT_NULL) && Z_BVAL_PP(not_null)) { \
5265: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected NULL for 'NOT NULL' field '%s'", field ); \
5266: err = 1; \
5267: } \
5268: }
5269:
5270: /* {{{ php_pgsql_convert
5271: * check and convert array values (fieldname=>vlaue pair) for sql
5272: */
5273: PHP_PGSQL_API int php_pgsql_convert(PGconn *pg_link, const char *table_name, const zval *values, zval *result, ulong opt TSRMLS_DC)
5274: {
5275: HashPosition pos;
5276: char *field = NULL;
5277: uint field_len = -1;
5278: ulong num_idx = -1;
1.1.1.3 ! misho 5279: zval *meta, **def, **type, **not_null, **has_default, **is_enum, **val, *new_val;
1.1 misho 5280: int new_len, key_type, err = 0, skip_field;
1.1.1.3 ! misho 5281: php_pgsql_data_type data_type;
1.1 misho 5282:
5283: assert(pg_link != NULL);
5284: assert(Z_TYPE_P(values) == IS_ARRAY);
5285: assert(Z_TYPE_P(result) == IS_ARRAY);
5286: assert(!(opt & ~PGSQL_CONV_OPTS));
5287:
5288: if (!table_name) {
5289: return FAILURE;
5290: }
5291: MAKE_STD_ZVAL(meta);
5292: array_init(meta);
5293: if (php_pgsql_meta_data(pg_link, table_name, meta TSRMLS_CC) == FAILURE) {
5294: zval_dtor(meta);
5295: FREE_ZVAL(meta);
5296: return FAILURE;
5297: }
5298: for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos);
5299: zend_hash_get_current_data_ex(Z_ARRVAL_P(values), (void **)&val, &pos) == SUCCESS;
5300: zend_hash_move_forward_ex(Z_ARRVAL_P(values), &pos)) {
5301: skip_field = 0;
5302: new_val = NULL;
5303:
5304: if ((key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(values), &field, &field_len, &num_idx, 0, &pos)) == HASH_KEY_NON_EXISTANT) {
5305: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to get array key type");
5306: err = 1;
5307: }
5308: if (!err && key_type == HASH_KEY_IS_LONG) {
5309: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Accepts only string key for values");
5310: err = 1;
5311: }
5312: if (!err && key_type == HASH_KEY_NON_EXISTANT) {
5313: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Accepts only string key for values");
5314: err = 1;
5315: }
5316: if (!err && zend_hash_find(Z_ARRVAL_P(meta), field, field_len, (void **)&def) == FAILURE) {
5317: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Invalid field name (%s) in values", field);
5318: err = 1;
5319: }
5320: if (!err && zend_hash_find(Z_ARRVAL_PP(def), "type", sizeof("type"), (void **)&type) == FAILURE) {
5321: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected broken meta data. Missing 'type'");
5322: err = 1;
5323: }
5324: if (!err && zend_hash_find(Z_ARRVAL_PP(def), "not null", sizeof("not null"), (void **)¬_null) == FAILURE) {
5325: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected broken meta data. Missing 'not null'");
5326: err = 1;
5327: }
5328: if (!err && zend_hash_find(Z_ARRVAL_PP(def), "has default", sizeof("has default"), (void **)&has_default) == FAILURE) {
5329: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected broken meta data. Missing 'has default'");
5330: err = 1;
5331: }
1.1.1.3 ! misho 5332: if (!err && zend_hash_find(Z_ARRVAL_PP(def), "is enum", sizeof("is enum"), (void **)&is_enum) == FAILURE) {
! 5333: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected broken meta data. Missing 'is enum'");
! 5334: err = 1;
! 5335: }
1.1 misho 5336: if (!err && (Z_TYPE_PP(val) == IS_ARRAY ||
5337: Z_TYPE_PP(val) == IS_OBJECT ||
5338: Z_TYPE_PP(val) == IS_CONSTANT_ARRAY)) {
1.1.1.3 ! misho 5339: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects scalar values as field values");
1.1 misho 5340: err = 1;
5341: }
5342: if (err) {
5343: break; /* break out for() */
5344: }
5345: ALLOC_INIT_ZVAL(new_val);
1.1.1.3 ! misho 5346:
! 5347: if (Z_BVAL_PP(is_enum)) {
! 5348: /* enums need to be treated like strings */
! 5349: data_type = PG_TEXT;
! 5350: }
! 5351: else {
! 5352: data_type = php_pgsql_get_data_type(Z_STRVAL_PP(type), Z_STRLEN_PP(type));
! 5353: }
! 5354:
! 5355: switch(data_type)
1.1 misho 5356: {
5357: case PG_BOOL:
5358: switch (Z_TYPE_PP(val)) {
5359: case IS_STRING:
5360: if (Z_STRLEN_PP(val) == 0) {
5361: ZVAL_STRING(new_val, "NULL", 1);
5362: }
5363: else {
5364: if (!strcmp(Z_STRVAL_PP(val), "t") || !strcmp(Z_STRVAL_PP(val), "T") ||
5365: !strcmp(Z_STRVAL_PP(val), "y") || !strcmp(Z_STRVAL_PP(val), "Y") ||
5366: !strcmp(Z_STRVAL_PP(val), "true") || !strcmp(Z_STRVAL_PP(val), "True") ||
5367: !strcmp(Z_STRVAL_PP(val), "yes") || !strcmp(Z_STRVAL_PP(val), "Yes") ||
5368: !strcmp(Z_STRVAL_PP(val), "1")) {
5369: ZVAL_STRING(new_val, "'t'", 1);
5370: }
5371: else if (!strcmp(Z_STRVAL_PP(val), "f") || !strcmp(Z_STRVAL_PP(val), "F") ||
5372: !strcmp(Z_STRVAL_PP(val), "n") || !strcmp(Z_STRVAL_PP(val), "N") ||
5373: !strcmp(Z_STRVAL_PP(val), "false") || !strcmp(Z_STRVAL_PP(val), "False") ||
5374: !strcmp(Z_STRVAL_PP(val), "no") || !strcmp(Z_STRVAL_PP(val), "No") ||
5375: !strcmp(Z_STRVAL_PP(val), "0")) {
5376: ZVAL_STRING(new_val, "'f'", 1);
5377: }
5378: else {
5379: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected invalid value (%s) for PostgreSQL %s field (%s)", Z_STRVAL_PP(val), Z_STRVAL_PP(type), field);
5380: err = 1;
5381: }
5382: }
5383: break;
5384:
5385: case IS_LONG:
5386: case IS_BOOL:
5387: if (Z_LVAL_PP(val)) {
5388: ZVAL_STRING(new_val, "'t'", 1);
5389: }
5390: else {
5391: ZVAL_STRING(new_val, "'f'", 1);
5392: }
5393: break;
5394:
5395: case IS_NULL:
5396: ZVAL_STRING(new_val, "NULL", 1);
5397: break;
5398:
5399: default:
5400: err = 1;
5401: }
5402: PGSQL_CONV_CHECK_IGNORE();
5403: if (err) {
5404: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects string, null, long or boolelan value for PostgreSQL '%s' (%s)", Z_STRVAL_PP(type), field);
5405: }
5406: break;
5407:
5408: case PG_OID:
5409: case PG_INT2:
5410: case PG_INT4:
5411: case PG_INT8:
5412: switch (Z_TYPE_PP(val)) {
5413: case IS_STRING:
5414: if (Z_STRLEN_PP(val) == 0) {
5415: ZVAL_STRING(new_val, "NULL", 1);
5416: }
5417: else {
5418: /* FIXME: better regex must be used */
5419: if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^([+-]{0,1}[0-9]+)$", 0 TSRMLS_CC) == FAILURE) {
5420: err = 1;
5421: }
5422: else {
5423: ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
5424: }
5425: }
5426: break;
5427:
5428: case IS_DOUBLE:
5429: ZVAL_DOUBLE(new_val, Z_DVAL_PP(val));
5430: convert_to_long_ex(&new_val);
5431: break;
5432:
5433: case IS_LONG:
5434: ZVAL_LONG(new_val, Z_LVAL_PP(val));
5435: break;
5436:
5437: case IS_NULL:
5438: ZVAL_STRING(new_val, "NULL", 1);
5439: break;
5440:
5441: default:
5442: err = 1;
5443: }
5444: PGSQL_CONV_CHECK_IGNORE();
5445: if (err) {
5446: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL, string, long or double value for pgsql '%s' (%s)", Z_STRVAL_PP(type), field);
5447: }
5448: break;
5449:
5450: case PG_NUMERIC:
5451: case PG_MONEY:
5452: case PG_FLOAT4:
5453: case PG_FLOAT8:
5454: switch (Z_TYPE_PP(val)) {
5455: case IS_STRING:
5456: if (Z_STRLEN_PP(val) == 0) {
5457: ZVAL_STRING(new_val, "NULL", 1);
5458: }
5459: else {
5460: /* FIXME: better regex must be used */
5461: if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^([+-]{0,1}[0-9]+)|([+-]{0,1}[0-9]*[\\.][0-9]+)|([+-]{0,1}[0-9]+[\\.][0-9]*)$", 0 TSRMLS_CC) == FAILURE) {
5462: err = 1;
5463: }
5464: else {
5465: ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
5466: }
5467: }
5468: break;
5469:
5470: case IS_LONG:
5471: ZVAL_LONG(new_val, Z_LVAL_PP(val));
5472: break;
5473:
5474: case IS_DOUBLE:
5475: ZVAL_DOUBLE(new_val, Z_DVAL_PP(val));
5476: break;
5477:
5478: case IS_NULL:
5479: ZVAL_STRING(new_val, "NULL", 1);
5480: break;
5481:
5482: default:
5483: err = 1;
5484: }
5485: PGSQL_CONV_CHECK_IGNORE();
5486: if (err) {
5487: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL, string, long or double value for PostgreSQL '%s' (%s)", Z_STRVAL_PP(type), field);
5488: }
5489: break;
5490:
5491: case PG_TEXT:
5492: case PG_CHAR:
5493: case PG_VARCHAR:
5494: switch (Z_TYPE_PP(val)) {
5495: case IS_STRING:
5496: if (Z_STRLEN_PP(val) == 0) {
5497: if (opt & PGSQL_CONV_FORCE_NULL) {
5498: ZVAL_STRING(new_val, "NULL", 1);
5499: } else {
5500: ZVAL_STRING(new_val, "''", 1);
5501: }
5502: }
5503: else {
5504: Z_TYPE_P(new_val) = IS_STRING;
5505: #if HAVE_PQESCAPE
5506: {
5507: char *tmp;
5508: tmp = (char *)safe_emalloc(Z_STRLEN_PP(val), 2, 1);
5509: Z_STRLEN_P(new_val) = (int)PQescapeString(tmp, Z_STRVAL_PP(val), Z_STRLEN_PP(val));
5510: Z_STRVAL_P(new_val) = tmp;
5511: }
5512: #else
5513: Z_STRVAL_P(new_val) = php_addslashes(Z_STRVAL_PP(val), Z_STRLEN_PP(val), &Z_STRLEN_P(new_val), 0 TSRMLS_CC);
5514: #endif
5515: php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
5516: }
5517: break;
5518:
5519: case IS_LONG:
5520: ZVAL_LONG(new_val, Z_LVAL_PP(val));
5521: convert_to_string_ex(&new_val);
5522: break;
5523:
5524: case IS_DOUBLE:
5525: ZVAL_DOUBLE(new_val, Z_DVAL_PP(val));
5526: convert_to_string_ex(&new_val);
5527: break;
5528:
5529: case IS_NULL:
5530: ZVAL_STRING(new_val, "NULL", 1);
5531: break;
5532:
5533: default:
5534: err = 1;
5535: }
5536: PGSQL_CONV_CHECK_IGNORE();
5537: if (err) {
5538: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL, string, long or double value for PostgreSQL '%s' (%s)", Z_STRVAL_PP(type), field);
5539: }
5540: break;
5541:
5542: case PG_UNIX_TIME:
5543: case PG_UNIX_TIME_INTERVAL:
5544: /* these are the actallay a integer */
5545: switch (Z_TYPE_PP(val)) {
5546: case IS_STRING:
5547: if (Z_STRLEN_PP(val) == 0) {
5548: ZVAL_STRING(new_val, "NULL", 1);
5549: }
5550: else {
5551: /* FIXME: Better regex must be used */
5552: if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^[0-9]+$", 0 TSRMLS_CC) == FAILURE) {
5553: err = 1;
5554: }
5555: else {
5556: ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
5557: convert_to_long_ex(&new_val);
5558: }
5559: }
5560: break;
5561:
5562: case IS_DOUBLE:
5563: ZVAL_DOUBLE(new_val, Z_DVAL_PP(val));
5564: convert_to_long_ex(&new_val);
5565: break;
5566:
5567: case IS_LONG:
5568: ZVAL_LONG(new_val, Z_LVAL_PP(val));
5569: break;
5570:
5571: case IS_NULL:
5572: ZVAL_STRING(new_val, "NULL", 1);
5573: break;
5574:
5575: default:
5576: err = 1;
5577: }
5578: PGSQL_CONV_CHECK_IGNORE();
5579: if (err) {
5580: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL, string, long or double value for '%s' (%s)", Z_STRVAL_PP(type), field);
5581: }
5582: break;
5583:
5584: case PG_CIDR:
5585: case PG_INET:
5586: switch (Z_TYPE_PP(val)) {
5587: case IS_STRING:
5588: if (Z_STRLEN_PP(val) == 0) {
5589: ZVAL_STRING(new_val, "NULL", 1);
5590: }
5591: else {
5592: /* FIXME: Better regex must be used */
5593: if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^([0-9]{1,3}\\.){3}[0-9]{1,3}(/[0-9]{1,2}){0,1}$", 0 TSRMLS_CC) == FAILURE) {
5594: err = 1;
5595: }
5596: else {
5597: ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
5598: php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
5599: }
5600: }
5601: break;
5602:
5603: case IS_NULL:
5604: ZVAL_STRING(new_val, "NULL", 1);
5605: break;
5606:
5607: default:
5608: err = 1;
5609: }
5610: PGSQL_CONV_CHECK_IGNORE();
5611: if (err) {
5612: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL or string for '%s' (%s)", Z_STRVAL_PP(type), field);
5613: }
5614: break;
5615:
5616: case PG_TIME_WITH_TIMEZONE:
5617: case PG_TIMESTAMP:
5618: case PG_TIMESTAMP_WITH_TIMEZONE:
5619: switch(Z_TYPE_PP(val)) {
5620: case IS_STRING:
5621: if (Z_STRLEN_PP(val) == 0) {
5622: ZVAL_STRINGL(new_val, "NULL", sizeof("NULL")-1, 1);
5623: } else if (!strcasecmp(Z_STRVAL_PP(val), "now()")) {
5624: ZVAL_STRINGL(new_val, "NOW()", sizeof("NOW()")-1, 1);
5625: } else {
5626: /* FIXME: better regex must be used */
5627: if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^([0-9]{4}[/-][0-9]{1,2}[/-][0-9]{1,2})([ \\t]+(([0-9]{1,2}:[0-9]{1,2}){1}(:[0-9]{1,2}){0,1}(\\.[0-9]+){0,1}([ \\t]*([+-][0-9]{1,4}(:[0-9]{1,2}){0,1}|[-a-zA-Z_/+]{1,50})){0,1})){0,1}$", 1 TSRMLS_CC) == FAILURE) {
5628: err = 1;
5629: } else {
5630: ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
5631: php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
5632: }
5633: }
5634: break;
5635:
5636: case IS_NULL:
5637: ZVAL_STRINGL(new_val, "NULL", sizeof("NULL")-1, 1);
5638: break;
5639:
5640: default:
5641: err = 1;
5642: }
5643: PGSQL_CONV_CHECK_IGNORE();
5644: if (err) {
5645: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL or string for PostgreSQL %s field (%s)", Z_STRVAL_PP(type), field);
5646: }
5647: break;
5648:
5649: case PG_DATE:
5650: switch(Z_TYPE_PP(val)) {
5651: case IS_STRING:
5652: if (Z_STRLEN_PP(val) == 0) {
5653: ZVAL_STRING(new_val, "NULL", 1);
5654: }
5655: else {
5656: /* FIXME: better regex must be used */
5657: if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^([0-9]{4}[/-][0-9]{1,2}[/-][0-9]{1,2})$", 1 TSRMLS_CC) == FAILURE) {
5658: err = 1;
5659: }
5660: else {
5661: ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
5662: php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
5663: }
5664: }
5665: break;
5666:
5667: case IS_NULL:
5668: ZVAL_STRING(new_val, "NULL", 1);
5669: break;
5670:
5671: default:
5672: err = 1;
5673: }
5674: PGSQL_CONV_CHECK_IGNORE();
5675: if (err) {
5676: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL or string for PostgreSQL %s field (%s)", Z_STRVAL_PP(type), field);
5677: }
5678: break;
5679:
5680: case PG_TIME:
5681: switch(Z_TYPE_PP(val)) {
5682: case IS_STRING:
5683: if (Z_STRLEN_PP(val) == 0) {
5684: ZVAL_STRING(new_val, "NULL", 1);
5685: }
5686: else {
5687: /* FIXME: better regex must be used */
5688: if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^(([0-9]{1,2}:[0-9]{1,2}){1}(:[0-9]{1,2}){0,1})){0,1}$", 1 TSRMLS_CC) == FAILURE) {
5689: err = 1;
5690: }
5691: else {
5692: ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
5693: php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
5694: }
5695: }
5696: break;
5697:
5698: case IS_NULL:
5699: ZVAL_STRING(new_val, "NULL", 1);
5700: break;
5701:
5702: default:
5703: err = 1;
5704: }
5705: PGSQL_CONV_CHECK_IGNORE();
5706: if (err) {
5707: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL or string for PostgreSQL %s field (%s)", Z_STRVAL_PP(type), field);
5708: }
5709: break;
5710:
5711: case PG_INTERVAL:
5712: switch(Z_TYPE_PP(val)) {
5713: case IS_STRING:
5714: if (Z_STRLEN_PP(val) == 0) {
5715: ZVAL_STRING(new_val, "NULL", 1);
5716: }
5717: else {
5718:
5719: /* From the Postgres docs:
5720:
5721: interval values can be written with the following syntax:
5722: [@] quantity unit [quantity unit...] [direction]
5723:
5724: Where: quantity is a number (possibly signed); unit is second, minute, hour,
5725: day, week, month, year, decade, century, millennium, or abbreviations or
5726: plurals of these units [note not *all* abbreviations] ; direction can be
5727: ago or empty. The at sign (@) is optional noise.
5728:
5729: ...
5730:
5731: Quantities of days, hours, minutes, and seconds can be specified without explicit
5732: unit markings. For example, '1 12:59:10' is read the same as '1 day 12 hours 59 min 10
5733: sec'.
5734: */
5735: if (php_pgsql_convert_match(Z_STRVAL_PP(val),
5736: "^(@?[ \\t]+)?("
5737:
5738: /* Textual time units and their abbreviations: */
5739: "(([-+]?[ \\t]+)?"
5740: "[0-9]+(\\.[0-9]*)?[ \\t]*"
5741: "(millenniums|millennia|millennium|mil|mils|"
5742: "centuries|century|cent|c|"
5743: "decades|decade|dec|decs|"
5744: "years|year|y|"
5745: "months|month|mon|"
5746: "weeks|week|w|"
5747: "days|day|d|"
5748: "hours|hour|hr|hrs|h|"
5749: "minutes|minute|mins|min|m|"
5750: "seconds|second|secs|sec|s))+|"
5751:
5752: /* Textual time units plus (dd)* hh[:mm[:ss]] */
5753: "((([-+]?[ \\t]+)?"
5754: "[0-9]+(\\.[0-9]*)?[ \\t]*"
5755: "(millenniums|millennia|millennium|mil|mils|"
5756: "centuries|century|cent|c|"
5757: "decades|decade|dec|decs|"
5758: "years|year|y|"
5759: "months|month|mon|"
5760: "weeks|week|w|"
5761: "days|day|d))+"
5762: "([-+]?[ \\t]+"
5763: "([0-9]+[ \\t]+)+" /* dd */
5764: "(([0-9]{1,2}:){0,2}[0-9]{0,2})" /* hh:[mm:[ss]] */
5765: ")?))"
5766: "([ \\t]+ago)?$",
5767: 1 TSRMLS_CC) == FAILURE) {
5768: err = 1;
5769: }
5770: else {
5771: ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
5772: php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
5773: }
5774: }
5775: break;
5776:
5777: case IS_NULL:
5778: ZVAL_STRING(new_val, "NULL", 1);
5779: break;
5780:
5781: default:
5782: err = 1;
5783: }
5784: PGSQL_CONV_CHECK_IGNORE();
5785: if (err) {
5786: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL or string for PostgreSQL %s field (%s)", Z_STRVAL_PP(type), field);
5787: }
5788: break;
5789: #ifdef HAVE_PQESCAPE
5790: case PG_BYTEA:
5791: switch (Z_TYPE_PP(val)) {
5792: case IS_STRING:
5793: if (Z_STRLEN_PP(val) == 0) {
5794: ZVAL_STRING(new_val, "NULL", 1);
5795: }
5796: else {
5797: unsigned char *tmp;
5798: size_t to_len;
5799: #ifdef HAVE_PQESCAPE_BYTEA_CONN
5800: tmp = PQescapeByteaConn(pg_link, Z_STRVAL_PP(val), Z_STRLEN_PP(val), &to_len);
5801: #else
5802: tmp = PQescapeBytea(Z_STRVAL_PP(val), Z_STRLEN_PP(val), &to_len);
5803: #endif
5804: Z_TYPE_P(new_val) = IS_STRING;
5805: Z_STRLEN_P(new_val) = to_len-1; /* PQescapeBytea's to_len includes additional '\0' */
5806: Z_STRVAL_P(new_val) = emalloc(to_len);
5807: memcpy(Z_STRVAL_P(new_val), tmp, to_len);
5808: PQfreemem(tmp);
5809: php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
5810:
5811: }
5812: break;
5813:
5814: case IS_LONG:
5815: ZVAL_LONG(new_val, Z_LVAL_PP(val));
5816: convert_to_string_ex(&new_val);
5817: break;
5818:
5819: case IS_DOUBLE:
5820: ZVAL_DOUBLE(new_val, Z_DVAL_PP(val));
5821: convert_to_string_ex(&new_val);
5822: break;
5823:
5824: case IS_NULL:
5825: ZVAL_STRING(new_val, "NULL", 1);
5826: break;
5827:
5828: default:
5829: err = 1;
5830: }
5831: PGSQL_CONV_CHECK_IGNORE();
5832: if (err) {
5833: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL, string, long or double value for PostgreSQL '%s' (%s)", Z_STRVAL_PP(type), field);
5834: }
5835: break;
5836:
5837: #endif
5838: case PG_MACADDR:
5839: switch(Z_TYPE_PP(val)) {
5840: case IS_STRING:
5841: if (Z_STRLEN_PP(val) == 0) {
5842: ZVAL_STRING(new_val, "NULL", 1);
5843: }
5844: else {
5845: if (php_pgsql_convert_match(Z_STRVAL_PP(val), "^([0-9a-f]{2,2}:){5,5}[0-9a-f]{2,2}$", 1 TSRMLS_CC) == FAILURE) {
5846: err = 1;
5847: }
5848: else {
5849: ZVAL_STRING(new_val, Z_STRVAL_PP(val), 1);
5850: php_pgsql_add_quotes(new_val, 1 TSRMLS_CC);
5851: }
5852: }
5853: break;
5854:
5855: case IS_NULL:
5856: ZVAL_STRING(new_val, "NULL", 1);
5857: break;
5858:
5859: default:
5860: err = 1;
5861: }
5862: PGSQL_CONV_CHECK_IGNORE();
5863: if (err) {
5864: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects NULL or string for PostgreSQL %s field (%s)", Z_STRVAL_PP(type), field);
5865: }
5866: break;
5867:
5868: /* bit */
5869: case PG_BIT:
5870: case PG_VARBIT:
5871: /* geometric */
5872: case PG_LINE:
5873: case PG_LSEG:
5874: case PG_POINT:
5875: case PG_BOX:
5876: case PG_PATH:
5877: case PG_POLYGON:
5878: case PG_CIRCLE:
5879: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "PostgreSQL '%s' type (%s) is not supported", Z_STRVAL_PP(type), field);
5880: err = 1;
5881: break;
5882:
5883: case PG_UNKNOWN:
5884: default:
5885: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown or system data type '%s' for '%s'", Z_STRVAL_PP(type), field);
5886: err = 1;
5887: break;
5888: } /* switch */
5889:
5890: if (err) {
5891: zval_dtor(new_val);
5892: FREE_ZVAL(new_val);
5893: break; /* break out for() */
5894: }
5895: if (!skip_field) {
5896: /* If field is NULL and HAS DEFAULT, should be skipped */
5897: field = php_addslashes(field, strlen(field), &new_len, 0 TSRMLS_CC);
5898: add_assoc_zval(result, field, new_val);
5899: efree(field);
5900: }
5901: } /* for */
5902: zval_dtor(meta);
5903: FREE_ZVAL(meta);
5904:
5905: if (err) {
5906: /* shouldn't destroy & free zval here */
5907: return FAILURE;
5908: }
5909: return SUCCESS;
5910: }
5911: /* }}} */
5912:
5913:
5914: /* {{{ proto array pg_convert(resource db, string table, array values[, int options])
5915: Check and convert values for PostgreSQL SQL statement */
5916: PHP_FUNCTION(pg_convert)
5917: {
5918: zval *pgsql_link, *values;
5919: char *table_name;
5920: int table_name_len;
5921: ulong option = 0;
5922: PGconn *pg_link;
5923: int id = -1;
5924:
5925: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
5926: "rsa|l", &pgsql_link, &table_name, &table_name_len, &values, &option) == FAILURE) {
5927: return;
5928: }
5929: if (option & ~PGSQL_CONV_OPTS) {
5930: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option is specified");
5931: RETURN_FALSE;
5932: }
5933: if (!table_name_len) {
5934: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Table name is invalid");
5935: RETURN_FALSE;
5936: }
5937:
5938: ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
5939:
5940: if (php_pgsql_flush_query(pg_link TSRMLS_CC)) {
5941: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected unhandled result(s) in connection");
5942: }
5943: array_init(return_value);
5944: if (php_pgsql_convert(pg_link, table_name, values, return_value, option TSRMLS_CC) == FAILURE) {
5945: zval_dtor(return_value);
5946: RETURN_FALSE;
5947: }
5948: }
5949: /* }}} */
5950:
5951: static int do_exec(smart_str *querystr, int expect, PGconn *pg_link, ulong opt TSRMLS_DC)
5952: {
5953: if (opt & PGSQL_DML_ASYNC) {
5954: if (PQsendQuery(pg_link, querystr->c)) {
5955: return 0;
5956: }
5957: }
5958: else {
5959: PGresult *pg_result;
5960:
5961: pg_result = PQexec(pg_link, querystr->c);
5962: if (PQresultStatus(pg_result) == expect) {
5963: PQclear(pg_result);
5964: return 0;
5965: } else {
5966: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", PQresultErrorMessage(pg_result));
5967: PQclear(pg_result);
5968: }
5969: }
5970:
5971: return -1;
5972: }
5973:
5974: /* {{{ php_pgsql_insert
5975: */
5976: PHP_PGSQL_API int php_pgsql_insert(PGconn *pg_link, const char *table, zval *var_array, ulong opt, char **sql TSRMLS_DC)
5977: {
5978: zval **val, *converted = NULL;
5979: char buf[256];
5980: char *fld;
5981: smart_str querystr = {0};
5982: int key_type, ret = FAILURE;
5983: uint fld_len;
5984: ulong num_idx;
5985: HashPosition pos;
5986:
5987: assert(pg_link != NULL);
5988: assert(table != NULL);
5989: assert(Z_TYPE_P(var_array) == IS_ARRAY);
5990:
5991: if (zend_hash_num_elements(Z_ARRVAL_P(var_array)) == 0) {
5992: smart_str_appends(&querystr, "INSERT INTO ");
5993: smart_str_appends(&querystr, table);
5994: smart_str_appends(&querystr, " DEFAULT VALUES");
5995:
5996: goto no_values;
5997: }
5998:
5999: /* convert input array if needed */
6000: if (!(opt & PGSQL_DML_NO_CONV)) {
6001: MAKE_STD_ZVAL(converted);
6002: array_init(converted);
6003: if (php_pgsql_convert(pg_link, table, var_array, converted, (opt & PGSQL_CONV_OPTS) TSRMLS_CC) == FAILURE) {
6004: goto cleanup;
6005: }
6006: var_array = converted;
6007: }
6008:
6009: smart_str_appends(&querystr, "INSERT INTO ");
6010: smart_str_appends(&querystr, table);
6011: smart_str_appends(&querystr, " (");
6012:
6013: zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(var_array), &pos);
6014: while ((key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(var_array), &fld,
6015: &fld_len, &num_idx, 0, &pos)) != HASH_KEY_NON_EXISTANT) {
6016: if (key_type == HASH_KEY_IS_LONG) {
6017: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects associative array for values to be inserted");
6018: goto cleanup;
6019: }
6020: smart_str_appendl(&querystr, fld, fld_len - 1);
6021: smart_str_appendc(&querystr, ',');
6022: zend_hash_move_forward_ex(Z_ARRVAL_P(var_array), &pos);
6023: }
6024: querystr.len--;
6025: smart_str_appends(&querystr, ") VALUES (");
6026:
6027: /* make values string */
6028: for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(var_array), &pos);
6029: zend_hash_get_current_data_ex(Z_ARRVAL_P(var_array), (void **)&val, &pos) == SUCCESS;
6030: zend_hash_move_forward_ex(Z_ARRVAL_P(var_array), &pos)) {
6031:
6032: /* we can avoid the key_type check here, because we tested it in the other loop */
6033: switch(Z_TYPE_PP(val)) {
6034: case IS_STRING:
6035: smart_str_appendl(&querystr, Z_STRVAL_PP(val), Z_STRLEN_PP(val));
6036: break;
6037: case IS_LONG:
6038: smart_str_append_long(&querystr, Z_LVAL_PP(val));
6039: break;
6040: case IS_DOUBLE:
6041: smart_str_appendl(&querystr, buf, snprintf(buf, sizeof(buf), "%F", Z_DVAL_PP(val)));
6042: break;
6043: default:
6044: /* should not happen */
6045: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Report this error to php-dev@lists.php.net, type = %d", Z_TYPE_PP(val));
6046: goto cleanup;
6047: break;
6048: }
6049: smart_str_appendc(&querystr, ',');
6050: }
6051: /* Remove the trailing "," */
6052: querystr.len--;
6053: smart_str_appends(&querystr, ");");
6054:
6055: no_values:
6056:
6057: smart_str_0(&querystr);
6058:
6059: if ((opt & (PGSQL_DML_EXEC|PGSQL_DML_ASYNC)) &&
6060: do_exec(&querystr, PGRES_COMMAND_OK, pg_link, (opt & PGSQL_CONV_OPTS) TSRMLS_CC) == 0) {
6061: ret = SUCCESS;
6062: }
6063: else if (opt & PGSQL_DML_STRING) {
6064: ret = SUCCESS;
6065: }
6066:
6067: cleanup:
6068: if (!(opt & PGSQL_DML_NO_CONV) && converted) {
6069: zval_dtor(converted);
6070: FREE_ZVAL(converted);
6071: }
6072: if (ret == SUCCESS && (opt & PGSQL_DML_STRING)) {
6073: *sql = querystr.c;
6074: }
6075: else {
6076: smart_str_free(&querystr);
6077: }
6078: return ret;
6079: }
6080: /* }}} */
6081:
6082: /* {{{ proto mixed pg_insert(resource db, string table, array values[, int options])
6083: Insert values (filed=>value) to table */
6084: PHP_FUNCTION(pg_insert)
6085: {
6086: zval *pgsql_link, *values;
6087: char *table, *sql = NULL;
6088: int table_len;
6089: ulong option = PGSQL_DML_EXEC;
6090: PGconn *pg_link;
6091: int id = -1, argc = ZEND_NUM_ARGS();
6092:
6093: if (zend_parse_parameters(argc TSRMLS_CC, "rsa|l",
6094: &pgsql_link, &table, &table_len, &values, &option) == FAILURE) {
6095: return;
6096: }
6097: if (option & ~(PGSQL_CONV_OPTS|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_ASYNC|PGSQL_DML_STRING)) {
6098: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option is specified");
6099: RETURN_FALSE;
6100: }
6101:
6102: ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
6103:
6104: if (php_pgsql_flush_query(pg_link TSRMLS_CC)) {
6105: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected unhandled result(s) in connection");
6106: }
6107: if (php_pgsql_insert(pg_link, table, values, option, &sql TSRMLS_CC) == FAILURE) {
6108: RETURN_FALSE;
6109: }
6110: if (option & PGSQL_DML_STRING) {
6111: RETURN_STRING(sql, 0);
6112: }
6113: RETURN_TRUE;
6114: }
6115: /* }}} */
6116:
6117: static inline int build_assignment_string(smart_str *querystr, HashTable *ht, int where_cond, const char *pad, int pad_len TSRMLS_DC)
6118: {
6119: HashPosition pos;
6120: uint fld_len;
6121: int key_type;
6122: ulong num_idx;
6123: char *fld;
6124: char buf[256];
6125: zval **val;
6126:
6127: for (zend_hash_internal_pointer_reset_ex(ht, &pos);
6128: zend_hash_get_current_data_ex(ht, (void **)&val, &pos) == SUCCESS;
6129: zend_hash_move_forward_ex(ht, &pos)) {
6130: key_type = zend_hash_get_current_key_ex(ht, &fld, &fld_len, &num_idx, 0, &pos);
6131: if (key_type == HASH_KEY_IS_LONG) {
6132: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects associative array for values to be inserted");
6133: return -1;
6134: }
6135: smart_str_appendl(querystr, fld, fld_len - 1);
6136: if (where_cond && Z_TYPE_PP(val) == IS_STRING && !strcmp(Z_STRVAL_PP(val), "NULL")) {
6137: smart_str_appends(querystr, " IS ");
6138: } else {
6139: smart_str_appendc(querystr, '=');
6140: }
6141:
6142: switch(Z_TYPE_PP(val)) {
6143: case IS_STRING:
6144: smart_str_appendl(querystr, Z_STRVAL_PP(val), Z_STRLEN_PP(val));
6145: break;
6146: case IS_LONG:
6147: smart_str_append_long(querystr, Z_LVAL_PP(val));
6148: break;
6149: case IS_DOUBLE:
6150: smart_str_appendl(querystr, buf, MIN(snprintf(buf, sizeof(buf), "%F", Z_DVAL_PP(val)), sizeof(buf)-1));
6151: break;
6152: default:
6153: /* should not happen */
6154: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Expects scaler values other than NULL. Need to convert?");
6155: return -1;
6156: }
6157: smart_str_appendl(querystr, pad, pad_len);
6158: }
6159: querystr->len -= pad_len;
6160:
6161: return 0;
6162: }
6163:
6164: /* {{{ php_pgsql_update
6165: */
6166: PHP_PGSQL_API int php_pgsql_update(PGconn *pg_link, const char *table, zval *var_array, zval *ids_array, ulong opt, char **sql TSRMLS_DC)
6167: {
6168: zval *var_converted = NULL, *ids_converted = NULL;
6169: smart_str querystr = {0};
6170: int ret = FAILURE;
6171:
6172: assert(pg_link != NULL);
6173: assert(table != NULL);
6174: assert(Z_TYPE_P(var_array) == IS_ARRAY);
6175: assert(Z_TYPE_P(ids_array) == IS_ARRAY);
6176: assert(!(opt & ~(PGSQL_CONV_OPTS|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_STRING)));
6177:
6178: if (zend_hash_num_elements(Z_ARRVAL_P(var_array)) == 0
6179: || zend_hash_num_elements(Z_ARRVAL_P(ids_array)) == 0) {
6180: return FAILURE;
6181: }
6182:
6183: if (!(opt & PGSQL_DML_NO_CONV)) {
6184: MAKE_STD_ZVAL(var_converted);
6185: array_init(var_converted);
6186: if (php_pgsql_convert(pg_link, table, var_array, var_converted, (opt & PGSQL_CONV_OPTS) TSRMLS_CC) == FAILURE) {
6187: goto cleanup;
6188: }
6189: var_array = var_converted;
6190: MAKE_STD_ZVAL(ids_converted);
6191: array_init(ids_converted);
6192: if (php_pgsql_convert(pg_link, table, ids_array, ids_converted, (opt & PGSQL_CONV_OPTS) TSRMLS_CC) == FAILURE) {
6193: goto cleanup;
6194: }
6195: ids_array = ids_converted;
6196: }
6197:
6198: smart_str_appends(&querystr, "UPDATE ");
6199: smart_str_appends(&querystr, table);
6200: smart_str_appends(&querystr, " SET ");
6201:
6202: if (build_assignment_string(&querystr, Z_ARRVAL_P(var_array), 0, ",", 1 TSRMLS_CC))
6203: goto cleanup;
6204:
6205: smart_str_appends(&querystr, " WHERE ");
6206:
6207: if (build_assignment_string(&querystr, Z_ARRVAL_P(ids_array), 1, " AND ", sizeof(" AND ")-1 TSRMLS_CC))
6208: goto cleanup;
6209:
6210: smart_str_appendc(&querystr, ';');
6211: smart_str_0(&querystr);
6212:
6213: if ((opt & PGSQL_DML_EXEC) && do_exec(&querystr, PGRES_COMMAND_OK, pg_link, opt TSRMLS_CC) == 0) {
6214: ret = SUCCESS;
6215: } else if (opt & PGSQL_DML_STRING) {
6216: ret = SUCCESS;
6217: }
6218:
6219: cleanup:
6220: if (var_converted) {
6221: zval_dtor(var_converted);
6222: FREE_ZVAL(var_converted);
6223: }
6224: if (ids_converted) {
6225: zval_dtor(ids_converted);
6226: FREE_ZVAL(ids_converted);
6227: }
6228: if (ret == SUCCESS && (opt & PGSQL_DML_STRING)) {
6229: *sql = querystr.c;
6230: }
6231: else {
6232: smart_str_free(&querystr);
6233: }
6234: return ret;
6235: }
6236: /* }}} */
6237:
6238: /* {{{ proto mixed pg_update(resource db, string table, array fields, array ids[, int options])
6239: Update table using values (field=>value) and ids (id=>value) */
6240: PHP_FUNCTION(pg_update)
6241: {
6242: zval *pgsql_link, *values, *ids;
6243: char *table, *sql = NULL;
6244: int table_len;
6245: ulong option = PGSQL_DML_EXEC;
6246: PGconn *pg_link;
6247: int id = -1, argc = ZEND_NUM_ARGS();
6248:
6249: if (zend_parse_parameters(argc TSRMLS_CC, "rsaa|l",
6250: &pgsql_link, &table, &table_len, &values, &ids, &option) == FAILURE) {
6251: return;
6252: }
6253: if (option & ~(PGSQL_CONV_OPTS|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_STRING)) {
6254: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option is specified");
6255: RETURN_FALSE;
6256: }
6257:
6258: ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
6259:
6260: if (php_pgsql_flush_query(pg_link TSRMLS_CC)) {
6261: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected unhandled result(s) in connection");
6262: }
6263: if (php_pgsql_update(pg_link, table, values, ids, option, &sql TSRMLS_CC) == FAILURE) {
6264: RETURN_FALSE;
6265: }
6266: if (option & PGSQL_DML_STRING) {
6267: RETURN_STRING(sql, 0);
6268: }
6269: RETURN_TRUE;
6270: }
6271: /* }}} */
6272:
6273: /* {{{ php_pgsql_delete
6274: */
6275: PHP_PGSQL_API int php_pgsql_delete(PGconn *pg_link, const char *table, zval *ids_array, ulong opt, char **sql TSRMLS_DC)
6276: {
6277: zval *ids_converted = NULL;
6278: smart_str querystr = {0};
6279: int ret = FAILURE;
6280:
6281: assert(pg_link != NULL);
6282: assert(table != NULL);
6283: assert(Z_TYPE_P(ids_array) == IS_ARRAY);
6284: assert(!(opt & ~(PGSQL_CONV_FORCE_NULL|PGSQL_DML_EXEC|PGSQL_DML_STRING)));
6285:
6286: if (zend_hash_num_elements(Z_ARRVAL_P(ids_array)) == 0) {
6287: return FAILURE;
6288: }
6289:
6290: if (!(opt & PGSQL_DML_NO_CONV)) {
6291: MAKE_STD_ZVAL(ids_converted);
6292: array_init(ids_converted);
6293: if (php_pgsql_convert(pg_link, table, ids_array, ids_converted, (opt & PGSQL_CONV_OPTS) TSRMLS_CC) == FAILURE) {
6294: goto cleanup;
6295: }
6296: ids_array = ids_converted;
6297: }
6298:
6299: smart_str_appends(&querystr, "DELETE FROM ");
6300: smart_str_appends(&querystr, table);
6301: smart_str_appends(&querystr, " WHERE ");
6302:
6303: if (build_assignment_string(&querystr, Z_ARRVAL_P(ids_array), 1, " AND ", sizeof(" AND ")-1 TSRMLS_CC))
6304: goto cleanup;
6305:
6306: smart_str_appendc(&querystr, ';');
6307: smart_str_0(&querystr);
6308:
6309: if ((opt & PGSQL_DML_EXEC) && do_exec(&querystr, PGRES_COMMAND_OK, pg_link, opt TSRMLS_CC) == 0) {
6310: ret = SUCCESS;
6311: } else if (opt & PGSQL_DML_STRING) {
6312: ret = SUCCESS;
6313: }
6314:
6315: cleanup:
6316: if (!(opt & PGSQL_DML_NO_CONV)) {
6317: zval_dtor(ids_converted);
6318: FREE_ZVAL(ids_converted);
6319: }
6320: if (ret == SUCCESS && (opt & PGSQL_DML_STRING)) {
6321: *sql = querystr.c;
6322: }
6323: else {
6324: smart_str_free(&querystr);
6325: }
6326: return ret;
6327: }
6328: /* }}} */
6329:
6330: /* {{{ proto mixed pg_delete(resource db, string table, array ids[, int options])
6331: Delete records has ids (id=>value) */
6332: PHP_FUNCTION(pg_delete)
6333: {
6334: zval *pgsql_link, *ids;
6335: char *table, *sql = NULL;
6336: int table_len;
6337: ulong option = PGSQL_DML_EXEC;
6338: PGconn *pg_link;
6339: int id = -1, argc = ZEND_NUM_ARGS();
6340:
6341: if (zend_parse_parameters(argc TSRMLS_CC, "rsa|l",
6342: &pgsql_link, &table, &table_len, &ids, &option) == FAILURE) {
6343: return;
6344: }
6345: if (option & ~(PGSQL_CONV_FORCE_NULL|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_STRING)) {
6346: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option is specified");
6347: RETURN_FALSE;
6348: }
6349:
6350: ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
6351:
6352: if (php_pgsql_flush_query(pg_link TSRMLS_CC)) {
6353: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected unhandled result(s) in connection");
6354: }
6355: if (php_pgsql_delete(pg_link, table, ids, option, &sql TSRMLS_CC) == FAILURE) {
6356: RETURN_FALSE;
6357: }
6358: if (option & PGSQL_DML_STRING) {
6359: RETURN_STRING(sql, 0);
6360: }
6361: RETURN_TRUE;
6362: }
6363: /* }}} */
6364:
6365: /* {{{ php_pgsql_result2array
6366: */
6367: PHP_PGSQL_API int php_pgsql_result2array(PGresult *pg_result, zval *ret_array TSRMLS_DC)
6368: {
6369: zval *row;
6370: char *field_name;
6371: size_t num_fields;
6372: int pg_numrows, pg_row;
6373: uint i;
6374: assert(Z_TYPE_P(ret_array) == IS_ARRAY);
6375:
6376: if ((pg_numrows = PQntuples(pg_result)) <= 0) {
6377: return FAILURE;
6378: }
6379: for (pg_row = 0; pg_row < pg_numrows; pg_row++) {
6380: MAKE_STD_ZVAL(row);
6381: array_init(row);
6382: add_index_zval(ret_array, pg_row, row);
6383: for (i = 0, num_fields = PQnfields(pg_result); i < num_fields; i++) {
6384: if (PQgetisnull(pg_result, pg_row, i)) {
6385: field_name = PQfname(pg_result, i);
6386: add_assoc_null(row, field_name);
6387: } else {
6388: char *element = PQgetvalue(pg_result, pg_row, i);
6389: if (element) {
6390: char *data;
6391: size_t data_len;
6392: const size_t element_len = strlen(element);
6393:
1.1.1.2 misho 6394: data = safe_estrndup(element, element_len);
6395: data_len = element_len;
6396:
1.1 misho 6397: field_name = PQfname(pg_result, i);
6398: add_assoc_stringl(row, field_name, data, data_len, 0);
6399: }
6400: }
6401: }
6402: }
6403: return SUCCESS;
6404: }
6405: /* }}} */
6406:
6407: /* {{{ php_pgsql_select
6408: */
6409: PHP_PGSQL_API int php_pgsql_select(PGconn *pg_link, const char *table, zval *ids_array, zval *ret_array, ulong opt, char **sql TSRMLS_DC)
6410: {
6411: zval *ids_converted = NULL;
6412: smart_str querystr = {0};
6413: int ret = FAILURE;
6414: PGresult *pg_result;
6415:
6416: assert(pg_link != NULL);
6417: assert(table != NULL);
6418: assert(Z_TYPE_P(ids_array) == IS_ARRAY);
6419: assert(Z_TYPE_P(ret_array) == IS_ARRAY);
6420: assert(!(opt & ~(PGSQL_CONV_OPTS|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_ASYNC|PGSQL_DML_STRING)));
6421:
6422: if (zend_hash_num_elements(Z_ARRVAL_P(ids_array)) == 0) {
6423: return FAILURE;
6424: }
6425:
6426: if (!(opt & PGSQL_DML_NO_CONV)) {
6427: MAKE_STD_ZVAL(ids_converted);
6428: array_init(ids_converted);
6429: if (php_pgsql_convert(pg_link, table, ids_array, ids_converted, (opt & PGSQL_CONV_OPTS) TSRMLS_CC) == FAILURE) {
6430: goto cleanup;
6431: }
6432: ids_array = ids_converted;
6433: }
6434:
6435: smart_str_appends(&querystr, "SELECT * FROM ");
6436: smart_str_appends(&querystr, table);
6437: smart_str_appends(&querystr, " WHERE ");
6438:
6439: if (build_assignment_string(&querystr, Z_ARRVAL_P(ids_array), 1, " AND ", sizeof(" AND ")-1 TSRMLS_CC))
6440: goto cleanup;
6441:
6442: smart_str_appendc(&querystr, ';');
6443: smart_str_0(&querystr);
6444:
6445: pg_result = PQexec(pg_link, querystr.c);
6446: if (PQresultStatus(pg_result) == PGRES_TUPLES_OK) {
6447: ret = php_pgsql_result2array(pg_result, ret_array TSRMLS_CC);
6448: } else {
6449: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Failed to execute '%s'", querystr.c);
6450: }
6451: PQclear(pg_result);
6452:
6453: cleanup:
6454: if (!(opt & PGSQL_DML_NO_CONV)) {
6455: zval_dtor(ids_converted);
6456: FREE_ZVAL(ids_converted);
6457: }
6458: if (ret == SUCCESS && (opt & PGSQL_DML_STRING)) {
6459: *sql = querystr.c;
6460: }
6461: else {
6462: smart_str_free(&querystr);
6463: }
6464: return ret;
6465: }
6466: /* }}} */
6467:
6468: /* {{{ proto mixed pg_select(resource db, string table, array ids[, int options])
6469: Select records that has ids (id=>value) */
6470: PHP_FUNCTION(pg_select)
6471: {
6472: zval *pgsql_link, *ids;
6473: char *table, *sql = NULL;
6474: int table_len;
6475: ulong option = PGSQL_DML_EXEC;
6476: PGconn *pg_link;
6477: int id = -1, argc = ZEND_NUM_ARGS();
6478:
6479: if (zend_parse_parameters(argc TSRMLS_CC, "rsa|l",
6480: &pgsql_link, &table, &table_len, &ids, &option) == FAILURE) {
6481: return;
6482: }
6483: if (option & ~(PGSQL_CONV_FORCE_NULL|PGSQL_DML_NO_CONV|PGSQL_DML_EXEC|PGSQL_DML_ASYNC|PGSQL_DML_STRING)) {
6484: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid option is specified");
6485: RETURN_FALSE;
6486: }
6487:
6488: ZEND_FETCH_RESOURCE2(pg_link, PGconn *, &pgsql_link, id, "PostgreSQL link", le_link, le_plink);
6489:
6490: if (php_pgsql_flush_query(pg_link TSRMLS_CC)) {
6491: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Detected unhandled result(s) in connection");
6492: }
6493: array_init(return_value);
6494: if (php_pgsql_select(pg_link, table, ids, return_value, option, &sql TSRMLS_CC) == FAILURE) {
6495: zval_dtor(return_value);
6496: RETURN_FALSE;
6497: }
6498: if (option & PGSQL_DML_STRING) {
6499: zval_dtor(return_value);
6500: RETURN_STRING(sql, 0);
6501: }
6502: return;
6503: }
6504: /* }}} */
6505:
6506: #endif
6507:
6508: /*
6509: * Local variables:
6510: * tab-width: 4
6511: * c-basic-offset: 4
6512: * End:
6513: * vim600: sw=4 ts=4 fdm=marker
6514: * vim<600: sw=4 ts=4
6515: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>