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