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