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