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