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