2 +--------------------------------------------------------------------+
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2013, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
18 #include <Zend/zend_interfaces.h>
19 #include <ext/standard/info.h>
20 #include <ext/spl/spl_array.h>
21 #include <ext/raphf/php_raphf.h>
23 #include <libpq-events.h>
24 #include <libpq/libpq-fs.h>
29 typedef int STATUS
; /* SUCCESS/FAILURE */
31 static char *rtrim(char *e
) {
34 while (l
-- > 0 && e
[l
] == '\n') {
40 #define PHP_PQerrorMessage(c) rtrim(PQerrorMessage((c)))
41 #define PHP_PQresultErrorMessage(r) rtrim(PQresultErrorMessage((r)))
43 static int php_pqconn_event(PGEventId id
, void *e
, void *data
);
45 #define PHP_PQclear(_r) \
47 zval *_resinszv = PQresultInstanceData((_r), php_pqconn_event); \
48 if (!_resinszv) PQclear((_r)); \
52 ZEND_DECLARE_MODULE_GLOBALS(pq)
58 /* Remove comments and fill if you need to have entries in php.ini
60 STD_PHP_INI_ENTRY("pq.global_value", "42", PHP_INI_ALL, OnUpdateLong, global_value, zend_pq_globals, pq_globals)
61 STD_PHP_INI_ENTRY("pq.global_string", "foobar", PHP_INI_ALL, OnUpdateString, global_string, zend_pq_globals, pq_globals)
66 /* {{{ php_pq_init_globals
68 /* Uncomment this function if you have INI entries
69 static void php_pq_init_globals(zend_pq_globals *pq_globals)
71 pq_globals->global_value = 0;
72 pq_globals->global_string = NULL;
77 static zend_class_entry
*php_pqconn_class_entry
;
78 static zend_class_entry
*php_pqtypes_class_entry
;
79 static zend_class_entry
*php_pqres_class_entry
;
80 static zend_class_entry
*php_pqstm_class_entry
;
81 static zend_class_entry
*php_pqtxn_class_entry
;
82 static zend_class_entry
*php_pqcancel_class_entry
;
83 static zend_class_entry
*php_pqevent_class_entry
;
84 static zend_class_entry
*php_pqlob_class_entry
;
85 static zend_class_entry
*php_pqcopy_class_entry
;
87 static zend_object_handlers php_pqconn_object_handlers
;
88 static zend_object_handlers php_pqtypes_object_handlers
;
89 static zend_object_handlers php_pqres_object_handlers
;
90 static zend_object_handlers php_pqstm_object_handlers
;
91 static zend_object_handlers php_pqtxn_object_handlers
;
92 static zend_object_handlers php_pqcancel_object_handlers
;
93 static zend_object_handlers php_pqevent_object_handlers
;
94 static zend_object_handlers php_pqlob_object_handlers
;
95 static zend_object_handlers php_pqcopy_object_handlers
;
97 typedef struct php_pq_callback
{
99 zend_fcall_info_cache fcc
;
103 typedef struct php_pq_object
{
105 zend_object_value zv
;
106 HashTable
*prophandler
;
110 #define PHP_PQCONN_ASYNC 0x01
111 #define PHP_PQCONN_PERSISTENT 0x02
113 typedef struct php_pqconn
{
115 int (*poller
)(PGconn
*);
116 php_resource_factory_t factory
;
118 HashTable eventhandlers
;
119 php_pq_callback_t onevent
;
120 unsigned unbuffered
:1;
123 typedef struct php_pqconn_object
{
125 zend_object_value zv
;
126 HashTable
*prophandler
;
127 php_pqconn_t
*intern
;
128 } php_pqconn_object_t
;
130 typedef struct php_pqtypes
{
132 php_pqconn_object_t
*conn
;
135 typedef struct php_pqtypes_object
{
137 zend_object_value zv
;
138 HashTable
*prophandler
;
139 php_pqtypes_t
*intern
;
140 } php_pqtypes_object_t
;
142 typedef struct php_pqconn_event_data
{
143 php_pqconn_object_t
*obj
;
147 } php_pqconn_event_data_t
;
149 typedef enum php_pqres_fetch
{
150 PHP_PQRES_FETCH_ARRAY
,
151 PHP_PQRES_FETCH_ASSOC
,
152 PHP_PQRES_FETCH_OBJECT
155 typedef struct php_pqres_iterator
{
156 zend_object_iterator zi
;
159 php_pqres_fetch_t fetch_type
;
160 } php_pqres_iterator_t
;
162 typedef struct php_pqres
{
164 php_pqres_iterator_t
*iter
;
168 typedef struct php_pqres_object
{
170 zend_object_value zv
;
171 HashTable
*prophandler
;
173 } php_pqres_object_t
;
175 typedef struct php_pqstm
{
176 php_pqconn_object_t
*conn
;
181 typedef struct php_pqstm_object
{
183 zend_object_value zv
;
184 HashTable
*prophandler
;
186 } php_pqstm_object_t
;
188 typedef enum php_pqtxn_isolation
{
189 PHP_PQTXN_READ_COMMITTED
,
190 PHP_PQTXN_REPEATABLE_READ
,
191 PHP_PQTXN_SERIALIZABLE
,
192 } php_pqtxn_isolation_t
;
194 typedef struct php_pqtxn
{
195 php_pqconn_object_t
*conn
;
196 php_pqtxn_isolation_t isolation
;
199 unsigned deferrable
:1;
202 typedef struct php_pqtxn_object
{
204 zend_object_value zv
;
205 HashTable
*prophandler
;
207 } php_pqtxn_object_t
;
209 typedef struct php_pqcancel
{
211 php_pqconn_object_t
*conn
;
214 typedef struct php_pqcancel_object
{
216 zend_object_value zv
;
217 HashTable
*prophandler
;
218 php_pqcancel_t
*intern
;
219 } php_pqcancel_object_t
;
221 typedef struct php_pqevent
{
222 php_pq_callback_t cb
;
223 php_pqconn_object_t
*conn
;
227 typedef struct php_pqevent_object
{
229 zend_object_value zv
;
230 HashTable
*prophandler
;
231 php_pqevent_t
*intern
;
232 } php_pqevent_object_t
;
234 typedef struct php_pqlob
{
237 php_pqtxn_object_t
*txn
;
240 typedef struct php_pqlob_object
{
242 zend_object_value zv
;
243 HashTable
*prophandler
;
245 } php_pqlob_object_t
;
247 typedef enum php_pqcopy_direction
{
248 PHP_PQCOPY_FROM_STDIN
,
250 } php_pqcopy_direction_t
;
252 typedef enum php_pqcopy_status
{
256 } php_pqcopy_status_t
;
258 typedef struct php_pqcopy
{
259 php_pqcopy_direction_t direction
;
262 php_pqconn_object_t
*conn
;
265 typedef struct php_pqcopy_object
{
267 zend_object_value zv
;
268 HashTable
*prophandler
;
269 php_pqcopy_t
*intern
;
270 } php_pqcopy_object_t
;
272 static HashTable php_pqconn_object_prophandlers
;
273 static HashTable php_pqtypes_object_prophandlers
;
274 static HashTable php_pqres_object_prophandlers
;
275 static HashTable php_pqstm_object_prophandlers
;
276 static HashTable php_pqtxn_object_prophandlers
;
277 static HashTable php_pqcancel_object_prophandlers
;
278 static HashTable php_pqevent_object_prophandlers
;
279 static HashTable php_pqlob_object_prophandlers
;
280 static HashTable php_pqcopy_object_prophandlers
;
282 typedef void (*php_pq_object_prophandler_func_t
)(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
);
284 typedef struct php_pq_object_prophandler
{
285 php_pq_object_prophandler_func_t read
;
286 php_pq_object_prophandler_func_t write
;
287 } php_pq_object_prophandler_t
;
289 static zend_object_iterator_funcs php_pqres_iterator_funcs
;
291 static zend_object_iterator
*php_pqres_iterator_init(zend_class_entry
*ce
, zval
*object
, int by_ref TSRMLS_DC
)
293 php_pqres_iterator_t
*iter
;
294 zval
*prop
, *zfetch_type
;
296 iter
= ecalloc(1, sizeof(*iter
));
297 iter
->zi
.funcs
= &php_pqres_iterator_funcs
;
298 iter
->zi
.data
= object
;
301 zfetch_type
= prop
= zend_read_property(ce
, object
, ZEND_STRL("fetchType"), 0 TSRMLS_CC
);
302 if (Z_TYPE_P(zfetch_type
) != IS_LONG
) {
303 convert_to_long_ex(&zfetch_type
);
305 iter
->fetch_type
= Z_LVAL_P(zfetch_type
);
306 if (zfetch_type
!= prop
) {
307 zval_ptr_dtor(&zfetch_type
);
309 if (Z_REFCOUNT_P(prop
)) {
310 zval_ptr_dtor(&prop
);
316 return (zend_object_iterator
*) iter
;
319 static void php_pqres_iterator_dtor(zend_object_iterator
*i TSRMLS_DC
)
321 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
323 if (iter
->current_val
) {
324 zval_ptr_dtor(&iter
->current_val
);
325 iter
->current_val
= NULL
;
327 zval_ptr_dtor((zval
**) &iter
->zi
.data
);
331 static STATUS
php_pqres_iterator_valid(zend_object_iterator
*i TSRMLS_DC
)
333 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
334 php_pqres_object_t
*obj
= zend_object_store_get_object(iter
->zi
.data TSRMLS_CC
);
336 if (PQresultStatus(obj
->intern
->res
) != PGRES_TUPLES_OK
) {
339 if (PQntuples(obj
->intern
->res
) <= iter
->index
) {
346 static zval
*php_pqres_row_to_zval(PGresult
*res
, unsigned row
, php_pqres_fetch_t fetch_type
, zval
**data_ptr TSRMLS_DC
)
356 if (PHP_PQRES_FETCH_OBJECT
== fetch_type
) {
366 for (c
= 0, cols
= PQnfields(res
); c
< cols
; ++c
) {
367 if (PQgetisnull(res
, row
, c
)) {
368 switch (fetch_type
) {
369 case PHP_PQRES_FETCH_OBJECT
:
370 add_property_null(data
, PQfname(res
, c
));
373 case PHP_PQRES_FETCH_ASSOC
:
374 add_assoc_null(data
, PQfname(res
, c
));
377 case PHP_PQRES_FETCH_ARRAY
:
378 add_index_null(data
, c
);
382 char *val
= PQgetvalue(res
, row
, c
);
383 int len
= PQgetlength(res
, row
, c
);
385 switch (fetch_type
) {
386 case PHP_PQRES_FETCH_OBJECT
:
387 add_property_stringl(data
, PQfname(res
, c
), val
, len
, 1);
390 case PHP_PQRES_FETCH_ASSOC
:
391 add_assoc_stringl(data
, PQfname(res
, c
), val
, len
, 1);
394 case PHP_PQRES_FETCH_ARRAY
:
395 add_index_stringl(data
, c
, val
, len
,1);
404 static void php_pqres_iterator_current(zend_object_iterator
*i
, zval
***data_ptr TSRMLS_DC
)
406 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
407 php_pqres_object_t
*obj
= zend_object_store_get_object(iter
->zi
.data TSRMLS_CC
);
409 if (iter
->current_val
) {
410 zval_ptr_dtor(&iter
->current_val
);
412 iter
->current_val
= php_pqres_row_to_zval(obj
->intern
->res
, iter
->index
, iter
->fetch_type
, NULL TSRMLS_CC
);
413 *data_ptr
= &iter
->current_val
;
416 static int php_pqres_iterator_key(zend_object_iterator
*i
, char **key_str
, uint
*key_len
, ulong
*key_num TSRMLS_DC
)
418 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
420 *key_num
= (ulong
) iter
->index
;
422 return HASH_KEY_IS_LONG
;
425 static void php_pqres_iterator_next(zend_object_iterator
*i TSRMLS_DC
)
427 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
432 static void php_pqres_iterator_rewind(zend_object_iterator
*i TSRMLS_DC
)
434 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
439 static zend_object_iterator_funcs php_pqres_iterator_funcs
= {
440 php_pqres_iterator_dtor
,
441 /* check for end of iteration (FAILURE or SUCCESS if data is valid) */
442 php_pqres_iterator_valid
,
443 /* fetch the item data for the current element */
444 php_pqres_iterator_current
,
445 /* fetch the key for the current element (return HASH_KEY_IS_STRING or HASH_KEY_IS_LONG) (optional, may be NULL) */
446 php_pqres_iterator_key
,
447 /* step forwards to next element */
448 php_pqres_iterator_next
,
449 /* rewind to start of data (optional, may be NULL) */
450 php_pqres_iterator_rewind
,
451 /* invalidate current value/key (optional, may be NULL) */
455 static int php_pqres_count_elements(zval
*object
, long *count TSRMLS_DC
)
457 php_pqres_object_t
*obj
= zend_object_store_get_object(object TSRMLS_CC
);
460 *count
= (long) PQntuples(obj
->intern
->res
);
467 static STATUS
php_pqres_success(PGresult
*res TSRMLS_DC
)
469 switch (PQresultStatus(res
)) {
470 case PGRES_BAD_RESPONSE
:
471 case PGRES_NONFATAL_ERROR
:
472 case PGRES_FATAL_ERROR
:
473 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "%s", PHP_PQresultErrorMessage(res
));
480 static void php_pq_callback_dtor(php_pq_callback_t
*cb
) {
481 if (cb
->fci
.size
> 0) {
482 zend_fcall_info_args_clear(&cb
->fci
, 1);
483 zval_ptr_dtor(&cb
->fci
.function_name
);
484 if (cb
->fci
.object_ptr
) {
485 zval_ptr_dtor(&cb
->fci
.object_ptr
);
491 static void php_pq_callback_addref(php_pq_callback_t
*cb
)
493 Z_ADDREF_P(cb
->fci
.function_name
);
494 if (cb
->fci
.object_ptr
) {
495 Z_ADDREF_P(cb
->fci
.object_ptr
);
499 static void php_pq_object_to_zval(void *o
, zval
**zv TSRMLS_DC
)
501 php_pq_object_t
*obj
= o
;
507 zend_objects_store_add_ref_by_handle(obj
->zv
.handle TSRMLS_CC
);
509 (*zv
)->type
= IS_OBJECT
;
510 (*zv
)->value
.obj
= obj
->zv
;
513 static void php_pq_object_addref(void *o TSRMLS_DC
)
515 php_pq_object_t
*obj
= o
;
516 zend_objects_store_add_ref_by_handle(obj
->zv
.handle TSRMLS_CC
);
519 static void php_pq_object_delref(void *o TSRMLS_DC
)
521 php_pq_object_t
*obj
= o
;
522 zend_objects_store_del_ref_by_handle_ex(obj
->zv
.handle
, obj
->zv
.handlers TSRMLS_CC
);
525 static int apply_unlisten(void *p TSRMLS_DC
, int argc
, va_list argv
, zend_hash_key
*key
)
527 php_pqconn_object_t
*obj
= va_arg(argv
, php_pqconn_object_t
*);
528 char *quoted_channel
= PQescapeIdentifier(obj
->intern
->conn
, key
->arKey
, key
->nKeyLength
- 1);
530 if (quoted_channel
) {
534 spprintf(&cmd
, 0, "UNLISTEN %s", quoted_channel
);
535 if ((res
= PQexec(obj
->intern
->conn
, cmd
))) {
540 PQfreemem(quoted_channel
);
543 return ZEND_HASH_APPLY_REMOVE
;
546 static void php_pqconn_notice_ignore(void *p
, const PGresult
*res
)
550 static void php_pqconn_object_free(void *o TSRMLS_DC
)
552 php_pqconn_object_t
*obj
= o
;
555 php_pqconn_event_data_t
*evdata
;
558 if ((evdata
= PQinstanceData(obj
->intern
->conn
, php_pqconn_event
))) {
559 memset(evdata
, 0, sizeof(*evdata
));
561 PQsetInstanceData(obj
->intern
->conn
, php_pqconn_event
, NULL
);
563 PQsetNoticeReceiver(obj
->intern
->conn
, php_pqconn_notice_ignore
, NULL
);
565 /* clean up async results */
566 while ((res
= PQgetResult(obj
->intern
->conn
))) {
570 zend_hash_apply_with_arguments(&obj
->intern
->listeners TSRMLS_CC
, apply_unlisten
, 1, obj
);
572 php_resource_factory_handle_dtor(&obj
->intern
->factory
, obj
->intern
->conn TSRMLS_CC
);
573 php_resource_factory_dtor(&obj
->intern
->factory
);
574 php_pq_callback_dtor(&obj
->intern
->onevent
);
575 zend_hash_destroy(&obj
->intern
->listeners
);
576 zend_hash_destroy(&obj
->intern
->eventhandlers
);
580 zend_object_std_dtor((zend_object
*) o TSRMLS_CC
);
584 static void php_pqtypes_object_free(void *o TSRMLS_DC
)
586 php_pqtypes_object_t
*obj
= o
;
589 zend_hash_destroy(&obj
->intern
->types
);
590 php_pq_object_delref(obj
->intern
->conn TSRMLS_CC
);
594 zend_object_std_dtor((zend_object
*) o TSRMLS_CC
);
598 static void php_pqres_object_free(void *o TSRMLS_DC
)
600 php_pqres_object_t
*obj
= o
;
603 if (obj
->intern
->res
) {
604 zval
*res
= PQresultInstanceData(obj
->intern
->res
, php_pqconn_event
);
606 if (1 == Z_REFCOUNT_P(res
)) {
607 PQresultSetInstanceData(obj
->intern
->res
, php_pqconn_event
, NULL
);
611 PQclear(obj
->intern
->res
);
612 obj
->intern
->res
= NULL
;
616 if (obj
->intern
->iter
) {
617 php_pqres_iterator_dtor((zend_object_iterator
*) obj
->intern
->iter TSRMLS_CC
);
618 obj
->intern
->iter
= NULL
;
621 zend_hash_destroy(&obj
->intern
->bound
);
626 zend_object_std_dtor((zend_object
*) o TSRMLS_CC
);
630 static void php_pqstm_object_free(void *o TSRMLS_DC
)
632 php_pqstm_object_t
*obj
= o
;
635 php_pq_object_delref(obj
->intern
->conn TSRMLS_CC
);
636 efree(obj
->intern
->name
);
637 zend_hash_destroy(&obj
->intern
->bound
);
641 zend_object_std_dtor((zend_object
*) o TSRMLS_CC
);
645 static void php_pqtxn_object_free(void *o TSRMLS_DC
)
647 php_pqtxn_object_t
*obj
= o
;
650 php_pq_object_delref(obj
->intern
->conn TSRMLS_CC
);
654 zend_object_std_dtor((zend_object
*) o TSRMLS_CC
);
658 static void php_pqcancel_object_free(void *o TSRMLS_DC
)
660 php_pqcancel_object_t
*obj
= o
;
663 PQfreeCancel(obj
->intern
->cancel
);
664 php_pq_object_delref(obj
->intern
->conn TSRMLS_CC
);
668 zend_object_std_dtor((zend_object
*) o TSRMLS_CC
);
672 static void php_pqevent_object_free(void *o TSRMLS_DC
)
674 php_pqevent_object_t
*obj
= o
;
677 php_pq_callback_dtor(&obj
->intern
->cb
);
678 php_pq_object_delref(obj
->intern
->conn TSRMLS_CC
);
679 efree(obj
->intern
->type
);
683 zend_object_std_dtor((zend_object
*) o TSRMLS_CC
);
687 static void php_pqlob_object_free(void *o TSRMLS_DC
)
689 php_pqlob_object_t
*obj
= o
;
692 if (obj
->intern
->lofd
) {
693 lo_close(obj
->intern
->txn
->intern
->conn
->intern
->conn
, obj
->intern
->lofd
);
695 php_pq_object_delref(obj
->intern
->txn TSRMLS_CC
);
699 zend_object_std_dtor((zend_object
*) o TSRMLS_CC
);
703 static void php_pqcopy_object_free(void *o TSRMLS_DC
)
705 php_pqcopy_object_t
*obj
= o
;
708 efree(obj
->intern
->expression
);
709 efree(obj
->intern
->options
);
710 php_pq_object_delref(obj
->intern
->conn TSRMLS_CC
);
714 zend_object_std_dtor((zend_object
*) o TSRMLS_CC
);
718 static zend_object_value
php_pqconn_create_object_ex(zend_class_entry
*ce
, php_pqconn_t
*intern
, php_pqconn_object_t
**ptr TSRMLS_DC
)
720 php_pqconn_object_t
*o
;
722 o
= ecalloc(1, sizeof(*o
));
723 zend_object_std_init((zend_object
*) o
, ce TSRMLS_CC
);
724 object_properties_init((zend_object
*) o
, ce
);
725 o
->prophandler
= &php_pqconn_object_prophandlers
;
735 o
->zv
.handle
= zend_objects_store_put((zend_object
*) o
, NULL
, php_pqconn_object_free
, NULL TSRMLS_CC
);
736 o
->zv
.handlers
= &php_pqconn_object_handlers
;
741 static zend_object_value
php_pqtypes_create_object_ex(zend_class_entry
*ce
, php_pqtypes_t
*intern
, php_pqtypes_object_t
**ptr TSRMLS_DC
)
743 php_pqtypes_object_t
*o
;
745 o
= ecalloc(1, sizeof(*o
));
746 zend_object_std_init((zend_object
*) o
, ce TSRMLS_CC
);
747 object_properties_init((zend_object
*) o
, ce
);
748 o
->prophandler
= &php_pqtypes_object_prophandlers
;
758 o
->zv
.handle
= zend_objects_store_put((zend_object
*) o
, NULL
, php_pqtypes_object_free
, NULL TSRMLS_CC
);
759 o
->zv
.handlers
= &php_pqtypes_object_handlers
;
764 static zend_object_value
php_pqres_create_object_ex(zend_class_entry
*ce
, php_pqres_t
*intern
, php_pqres_object_t
**ptr TSRMLS_DC
)
766 php_pqres_object_t
*o
;
768 o
= ecalloc(1, sizeof(*o
));
769 zend_object_std_init((zend_object
*) o
, ce TSRMLS_CC
);
770 object_properties_init((zend_object
*) o
, ce
);
771 o
->prophandler
= &php_pqres_object_prophandlers
;
781 o
->zv
.handle
= zend_objects_store_put((zend_object
*) o
, NULL
, php_pqres_object_free
, NULL TSRMLS_CC
);
782 o
->zv
.handlers
= &php_pqres_object_handlers
;
787 static zend_object_value
php_pqstm_create_object_ex(zend_class_entry
*ce
, php_pqstm_t
*intern
, php_pqstm_object_t
**ptr TSRMLS_DC
)
789 php_pqstm_object_t
*o
;
791 o
= ecalloc(1, sizeof(*o
));
792 zend_object_std_init((zend_object
*) o
, ce TSRMLS_CC
);
793 object_properties_init((zend_object
*) o
, ce
);
794 o
->prophandler
= &php_pqstm_object_prophandlers
;
804 o
->zv
.handle
= zend_objects_store_put((zend_object
*) o
, NULL
, php_pqstm_object_free
, NULL TSRMLS_CC
);
805 o
->zv
.handlers
= &php_pqstm_object_handlers
;
810 static zend_object_value
php_pqtxn_create_object_ex(zend_class_entry
*ce
, php_pqtxn_t
*intern
, php_pqtxn_object_t
**ptr TSRMLS_DC
)
812 php_pqtxn_object_t
*o
;
814 o
= ecalloc(1, sizeof(*o
));
815 zend_object_std_init((zend_object
*) o
, ce TSRMLS_CC
);
816 object_properties_init((zend_object
*) o
, ce
);
817 o
->prophandler
= &php_pqtxn_object_prophandlers
;
827 o
->zv
.handle
= zend_objects_store_put((zend_object
*) o
, NULL
, php_pqtxn_object_free
, NULL TSRMLS_CC
);
828 o
->zv
.handlers
= &php_pqtxn_object_handlers
;
833 static zend_object_value
php_pqcancel_create_object_ex(zend_class_entry
*ce
, php_pqcancel_t
*intern
, php_pqcancel_object_t
**ptr TSRMLS_DC
)
835 php_pqcancel_object_t
*o
;
837 o
= ecalloc(1, sizeof(*o
));
838 zend_object_std_init((zend_object
*) o
, ce TSRMLS_CC
);
839 object_properties_init((zend_object
*) o
, ce
);
840 o
->prophandler
= &php_pqcancel_object_prophandlers
;
850 o
->zv
.handle
= zend_objects_store_put((zend_object
*) o
, NULL
, php_pqcancel_object_free
, NULL TSRMLS_CC
);
851 o
->zv
.handlers
= &php_pqcancel_object_handlers
;
856 static zend_object_value
php_pqevent_create_object_ex(zend_class_entry
*ce
, php_pqevent_t
*intern
, php_pqevent_object_t
**ptr TSRMLS_DC
)
858 php_pqevent_object_t
*o
;
860 o
= ecalloc(1, sizeof(*o
));
861 zend_object_std_init((zend_object
*) o
, ce TSRMLS_CC
);
862 object_properties_init((zend_object
*) o
, ce
);
863 o
->prophandler
= &php_pqevent_object_prophandlers
;
873 o
->zv
.handle
= zend_objects_store_put((zend_object
*) o
, NULL
, php_pqevent_object_free
, NULL TSRMLS_CC
);
874 o
->zv
.handlers
= &php_pqevent_object_handlers
;
879 static zend_object_value
php_pqlob_create_object_ex(zend_class_entry
*ce
, php_pqlob_t
*intern
, php_pqlob_object_t
**ptr TSRMLS_DC
)
881 php_pqlob_object_t
*o
;
883 o
= ecalloc(1, sizeof(*o
));
884 zend_object_std_init((zend_object
*) o
, ce TSRMLS_CC
);
885 object_properties_init((zend_object
*) o
, ce
);
886 o
->prophandler
= &php_pqlob_object_prophandlers
;
896 o
->zv
.handle
= zend_objects_store_put((zend_object
*) o
, NULL
, php_pqlob_object_free
, NULL TSRMLS_CC
);
897 o
->zv
.handlers
= &php_pqlob_object_handlers
;
902 static zend_object_value
php_pqcopy_create_object_ex(zend_class_entry
*ce
, php_pqcopy_t
*intern
, php_pqcopy_object_t
**ptr TSRMLS_DC
)
904 php_pqcopy_object_t
*o
;
906 o
= ecalloc(1, sizeof(*o
));
907 zend_object_std_init((zend_object
*) o
, ce TSRMLS_CC
);
908 object_properties_init((zend_object
*) o
, ce
);
909 o
->prophandler
= &php_pqcopy_object_prophandlers
;
919 o
->zv
.handle
= zend_objects_store_put((zend_object
*) o
, NULL
, php_pqcopy_object_free
, NULL TSRMLS_CC
);
920 o
->zv
.handlers
= &php_pqcopy_object_handlers
;
925 static zend_object_value
php_pqconn_create_object(zend_class_entry
*class_type TSRMLS_DC
)
927 return php_pqconn_create_object_ex(class_type
, NULL
, NULL TSRMLS_CC
);
930 static zend_object_value
php_pqtypes_create_object(zend_class_entry
*class_type TSRMLS_DC
)
932 return php_pqtypes_create_object_ex(class_type
, NULL
, NULL TSRMLS_CC
);
935 static zend_object_value
php_pqres_create_object(zend_class_entry
*class_type TSRMLS_DC
)
937 return php_pqres_create_object_ex(class_type
, NULL
, NULL TSRMLS_CC
);
940 static zend_object_value
php_pqstm_create_object(zend_class_entry
*class_type TSRMLS_DC
)
942 return php_pqstm_create_object_ex(class_type
, NULL
, NULL TSRMLS_CC
);
945 static zend_object_value
php_pqtxn_create_object(zend_class_entry
*class_type TSRMLS_DC
)
947 return php_pqtxn_create_object_ex(class_type
, NULL
, NULL TSRMLS_CC
);
950 static zend_object_value
php_pqcancel_create_object(zend_class_entry
*class_type TSRMLS_DC
)
952 return php_pqcancel_create_object_ex(class_type
, NULL
, NULL TSRMLS_CC
);
955 static zend_object_value
php_pqevent_create_object(zend_class_entry
*class_type TSRMLS_DC
)
957 return php_pqevent_create_object_ex(class_type
, NULL
, NULL TSRMLS_CC
);
960 static zend_object_value
php_pqlob_create_object(zend_class_entry
*class_type TSRMLS_DC
)
962 return php_pqlob_create_object_ex(class_type
, NULL
, NULL TSRMLS_CC
);
965 static zend_object_value
php_pqcopy_create_object(zend_class_entry
*class_type TSRMLS_DC
)
967 return php_pqcopy_create_object_ex(class_type
, NULL
, NULL TSRMLS_CC
);
970 static int apply_ph_to_debug(void *p TSRMLS_DC
, int argc
, va_list argv
, zend_hash_key
*key
)
972 php_pq_object_prophandler_t
*ph
= p
;
973 HashTable
*ht
= va_arg(argv
, HashTable
*);
974 zval
**return_value
, *object
= va_arg(argv
, zval
*);
975 php_pq_object_t
*obj
= va_arg(argv
, php_pq_object_t
*);
977 if (SUCCESS
== zend_hash_find(ht
, key
->arKey
, key
->nKeyLength
, (void *) &return_value
)) {
980 zval_ptr_dtor(return_value
);
981 MAKE_STD_ZVAL(*return_value
);
982 ZVAL_NULL(*return_value
);
984 ph
->read(object
, obj
, *return_value TSRMLS_CC
);
988 return ZEND_HASH_APPLY_KEEP
;
991 static int apply_pi_to_debug(void *p TSRMLS_DC
, int argc
, va_list argv
, zend_hash_key
*key
)
993 zend_property_info
*pi
= p
;
994 HashTable
*ht
= va_arg(argv
, HashTable
*);
995 zval
*object
= va_arg(argv
, zval
*);
996 php_pq_object_t
*obj
= va_arg(argv
, php_pq_object_t
*);
997 zval
*property
= zend_read_property(obj
->zo
.ce
, object
, pi
->name
, pi
->name_length
, 0 TSRMLS_CC
);
999 if (1||!Z_REFCOUNT_P(property
)) {
1000 Z_ADDREF_P(property
);
1002 zend_hash_add(ht
, pi
->name
, pi
->name_length
+ 1, (void *) &property
, sizeof(zval
*), NULL
);
1004 return ZEND_HASH_APPLY_KEEP
;
1007 static HashTable
*php_pq_object_debug_info(zval
*object
, int *temp TSRMLS_DC
)
1010 php_pq_object_t
*obj
= zend_object_store_get_object(object TSRMLS_CC
);
1013 ALLOC_HASHTABLE(ht
);
1014 ZEND_INIT_SYMTABLE(ht
);
1016 zend_hash_apply_with_arguments(&obj
->zo
.ce
->properties_info TSRMLS_CC
, apply_pi_to_debug
, 3, ht
, object
, obj
);
1017 zend_hash_apply_with_arguments(obj
->prophandler TSRMLS_CC
, apply_ph_to_debug
, 3, ht
, object
, obj
);
1022 static void php_pqconn_object_read_status(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1024 php_pqconn_object_t
*obj
= o
;
1026 RETVAL_LONG(PQstatus(obj
->intern
->conn
));
1029 static void php_pqconn_object_read_transaction_status(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1031 php_pqconn_object_t
*obj
= o
;
1033 RETVAL_LONG(PQtransactionStatus(obj
->intern
->conn
));
1036 static void php_pqconn_object_read_error_message(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1038 php_pqconn_object_t
*obj
= o
;
1039 char *error
= PHP_PQerrorMessage(obj
->intern
->conn
);
1042 RETVAL_STRING(error
, 1);
1048 static int apply_notify_listener(void *p
, void *arg TSRMLS_DC
)
1050 php_pq_callback_t
*listener
= p
;
1051 PGnotify
*nfy
= arg
;
1052 zval
*zpid
, *zchannel
, *zmessage
;
1054 MAKE_STD_ZVAL(zpid
);
1055 ZVAL_LONG(zpid
, nfy
->be_pid
);
1056 MAKE_STD_ZVAL(zchannel
);
1057 ZVAL_STRING(zchannel
, nfy
->relname
, 1);
1058 MAKE_STD_ZVAL(zmessage
);
1059 ZVAL_STRING(zmessage
, nfy
->extra
, 1);
1061 zend_fcall_info_argn(&listener
->fci TSRMLS_CC
, 3, &zchannel
, &zmessage
, &zpid
);
1062 zend_fcall_info_call(&listener
->fci
, &listener
->fcc
, NULL
, NULL TSRMLS_CC
);
1064 zval_ptr_dtor(&zchannel
);
1065 zval_ptr_dtor(&zmessage
);
1066 zval_ptr_dtor(&zpid
);
1068 return ZEND_HASH_APPLY_KEEP
;
1071 static int apply_notify_listeners(void *p TSRMLS_DC
, int argc
, va_list argv
, zend_hash_key
*key
)
1073 HashTable
*listeners
= p
;
1074 PGnotify
*nfy
= va_arg(argv
, PGnotify
*);
1076 if (0 == fnmatch(key
->arKey
, nfy
->relname
, 0)) {
1077 zend_hash_apply_with_argument(listeners
, apply_notify_listener
, nfy TSRMLS_CC
);
1080 return ZEND_HASH_APPLY_KEEP
;
1083 static void php_pqconn_notify_listeners(php_pqconn_object_t
*obj TSRMLS_DC
)
1087 while ((nfy
= PQnotifies(obj
->intern
->conn
))) {
1088 zend_hash_apply_with_arguments(&obj
->intern
->listeners TSRMLS_CC
, apply_notify_listeners
, 1, nfy
);
1093 static void php_pqconn_object_read_busy(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1095 php_pqconn_object_t
*obj
= o
;
1097 RETVAL_BOOL(PQisBusy(obj
->intern
->conn
));
1100 static void php_pqconn_object_read_encoding(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1102 php_pqconn_object_t
*obj
= o
;
1104 RETVAL_STRING(pg_encoding_to_char(PQclientEncoding(obj
->intern
->conn
)), 1);
1107 static void php_pqconn_object_write_encoding(zval
*object
, void *o
, zval
*value TSRMLS_DC
)
1109 php_pqconn_object_t
*obj
= o
;
1112 if (Z_TYPE_P(value
) != IS_STRING
) {
1113 convert_to_string_ex(&zenc
);
1116 if (0 > PQsetClientEncoding(obj
->intern
->conn
, Z_STRVAL_P(zenc
))) {
1117 zend_error(E_NOTICE
, "Unrecognized encoding '%s'", Z_STRVAL_P(zenc
));
1120 if (zenc
!= value
) {
1121 zval_ptr_dtor(&zenc
);
1125 static void php_pqconn_object_read_unbuffered(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1127 php_pqconn_object_t
*obj
= o
;
1129 RETVAL_BOOL(obj
->intern
->unbuffered
);
1132 static void php_pqconn_object_write_unbuffered(zval
*object
, void *o
, zval
*value TSRMLS_DC
)
1134 php_pqconn_object_t
*obj
= o
;
1136 obj
->intern
->unbuffered
= zend_is_true(value
);
1139 static void php_pqconn_object_read_db(zval
*objec
, void *o
, zval
*return_value TSRMLS_DC
)
1141 php_pqconn_object_t
*obj
= o
;
1142 char *db
= PQdb(obj
->intern
->conn
);
1145 RETVAL_STRING(db
, 1);
1147 RETVAL_EMPTY_STRING();
1151 static void php_pqconn_object_read_user(zval
*objec
, void *o
, zval
*return_value TSRMLS_DC
)
1153 php_pqconn_object_t
*obj
= o
;
1154 char *user
= PQuser(obj
->intern
->conn
);
1157 RETVAL_STRING(user
, 1);
1159 RETVAL_EMPTY_STRING();
1163 static void php_pqconn_object_read_pass(zval
*objec
, void *o
, zval
*return_value TSRMLS_DC
)
1165 php_pqconn_object_t
*obj
= o
;
1166 char *pass
= PQpass(obj
->intern
->conn
);
1169 RETVAL_STRING(pass
, 1);
1171 RETVAL_EMPTY_STRING();
1175 static void php_pqconn_object_read_host(zval
*objec
, void *o
, zval
*return_value TSRMLS_DC
)
1177 php_pqconn_object_t
*obj
= o
;
1178 char *host
= PQhost(obj
->intern
->conn
);
1181 RETVAL_STRING(host
, 1);
1183 RETVAL_EMPTY_STRING();
1187 static void php_pqconn_object_read_port(zval
*objec
, void *o
, zval
*return_value TSRMLS_DC
)
1189 php_pqconn_object_t
*obj
= o
;
1190 char *port
= PQport(obj
->intern
->conn
);
1193 RETVAL_STRING(port
, 1);
1195 RETVAL_EMPTY_STRING();
1199 static void php_pqconn_object_read_options(zval
*objec
, void *o
, zval
*return_value TSRMLS_DC
)
1201 php_pqconn_object_t
*obj
= o
;
1202 char *options
= PQoptions(obj
->intern
->conn
);
1205 RETVAL_STRING(options
, 1);
1207 RETVAL_EMPTY_STRING();
1211 static void php_pqtypes_object_read_connection(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1213 php_pqtypes_object_t
*obj
= o
;
1215 php_pq_object_to_zval(obj
->intern
->conn
, &return_value TSRMLS_CC
);
1218 static int has_dimension(HashTable
*ht
, zval
*member
, char **key_str
, int *key_len
, long *index TSRMLS_DC
)
1223 switch (Z_TYPE_P(member
)) {
1225 convert_to_string_ex(&tmp
);
1228 if (!is_numeric_string(Z_STRVAL_P(tmp
), Z_STRLEN_P(tmp
), &lval
, NULL
, 0)) {
1229 if (member
!= tmp
) {
1230 zval_ptr_dtor(&tmp
);
1233 *key_str
= estrndup(Z_STRVAL_P(tmp
), Z_STRLEN_P(tmp
));
1235 *key_len
= Z_STRLEN_P(tmp
) + 1;
1238 return zend_hash_exists(ht
, Z_STRVAL_P(tmp
), Z_STRLEN_P(tmp
) + 1);
1242 lval
= Z_LVAL_P(member
);
1246 if (member
!= tmp
) {
1247 zval_ptr_dtor(&tmp
);
1252 return zend_hash_index_exists(ht
, lval
);
1255 static int php_pqtypes_object_has_dimension(zval
*object
, zval
*member
, int check_empty TSRMLS_DC
)
1257 php_pqtypes_object_t
*obj
= zend_object_store_get_object(object TSRMLS_CC
);
1258 char *key_str
= NULL
;
1263 if (has_dimension(&obj
->intern
->types
, member
, &key_str
, &key_len
, &index TSRMLS_CC
)) {
1266 if (key_str
&& key_len
) {
1267 if (SUCCESS
== zend_hash_find(&obj
->intern
->types
, key_str
, key_len
, (void *) &data
)) {
1269 return Z_TYPE_PP(data
) != IS_NULL
;
1273 if (SUCCESS
== zend_hash_index_find(&obj
->intern
->types
, index
, (void *) data
)) {
1274 return Z_TYPE_PP(data
) != IS_NULL
;
1279 return has_dimension(&obj
->intern
->types
, member
, NULL
, NULL
, NULL TSRMLS_CC
);
1285 static zval
*php_pqtypes_object_read_dimension(zval
*object
, zval
*member
, int type TSRMLS_DC
)
1288 char *key_str
= NULL
;
1290 php_pqtypes_object_t
*obj
= zend_object_store_get_object(object TSRMLS_CC
);
1292 if (has_dimension(&obj
->intern
->types
, member
, &key_str
, &key_len
, &index TSRMLS_CC
)) {
1295 if (key_str
&& key_len
) {
1296 if (SUCCESS
== zend_hash_find(&obj
->intern
->types
, key_str
, key_len
, (void *) &data
)) {
1301 if (SUCCESS
== zend_hash_index_find(&obj
->intern
->types
, index
, (void *) &data
)) {
1310 static void php_pqres_object_read_status(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1312 php_pqres_object_t
*obj
= o
;
1314 RETVAL_LONG(PQresultStatus(obj
->intern
->res
));
1317 static void php_pqres_object_read_error_message(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1319 php_pqres_object_t
*obj
= o
;
1320 char *error
= PHP_PQresultErrorMessage(obj
->intern
->res
);
1323 RETVAL_STRING(error
, 1);
1329 static void php_pqres_object_read_num_rows(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1331 php_pqres_object_t
*obj
= o
;
1333 RETVAL_LONG(PQntuples(obj
->intern
->res
));
1336 static void php_pqres_object_read_num_cols(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1338 php_pqres_object_t
*obj
= o
;
1340 RETVAL_LONG(PQnfields(obj
->intern
->res
));
1343 static void php_pqres_object_read_affected_rows(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1345 php_pqres_object_t
*obj
= o
;
1347 RETVAL_LONG(atoi(PQcmdTuples(obj
->intern
->res
)));
1350 static void php_pqres_object_read_fetch_type(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1352 php_pqres_object_t
*obj
= o
;
1354 if (obj
->intern
->iter
) {
1355 RETVAL_LONG(obj
->intern
->iter
->fetch_type
);
1357 RETVAL_LONG(PHP_PQRES_FETCH_ARRAY
);
1361 static void php_pqres_object_write_fetch_type(zval
*object
, void *o
, zval
*value TSRMLS_DC
)
1363 php_pqres_object_t
*obj
= o
;
1364 zval
*zfetch_type
= value
;
1366 if (Z_TYPE_P(zfetch_type
) != IS_LONG
) {
1367 convert_to_long_ex(&zfetch_type
);
1370 if (!obj
->intern
->iter
) {
1371 obj
->intern
->iter
= (php_pqres_iterator_t
*) php_pqres_iterator_init(Z_OBJCE_P(object
), object
, 0 TSRMLS_CC
);
1372 obj
->intern
->iter
->zi
.funcs
->rewind((zend_object_iterator
*) obj
->intern
->iter TSRMLS_CC
);
1374 obj
->intern
->iter
->fetch_type
= Z_LVAL_P(zfetch_type
);
1376 if (zfetch_type
!= value
) {
1377 zval_ptr_dtor(&zfetch_type
);
1381 static void php_pqstm_object_read_name(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1383 php_pqstm_object_t
*obj
= o
;
1385 RETVAL_STRING(obj
->intern
->name
, 1);
1388 static void php_pqstm_object_read_connection(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1390 php_pqstm_object_t
*obj
= o
;
1392 php_pq_object_to_zval(obj
->intern
->conn
, &return_value TSRMLS_CC
);
1395 static void php_pqtxn_object_read_connection(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1397 php_pqtxn_object_t
*obj
= o
;
1399 php_pq_object_to_zval(obj
->intern
->conn
, &return_value TSRMLS_CC
);
1402 static void php_pqtxn_object_read_isolation(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1404 php_pqtxn_object_t
*obj
= o
;
1406 RETVAL_LONG(obj
->intern
->isolation
);
1409 static void php_pqtxn_object_read_readonly(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1411 php_pqtxn_object_t
*obj
= o
;
1413 RETVAL_LONG(obj
->intern
->readonly
);
1416 static void php_pqtxn_object_read_deferrable(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1418 php_pqtxn_object_t
*obj
= o
;
1420 RETVAL_LONG(obj
->intern
->deferrable
);
1423 static void php_pqtxn_object_write_isolation(zval
*object
, void *o
, zval
*value TSRMLS_DC
)
1425 php_pqtxn_object_t
*obj
= o
;
1426 php_pqtxn_isolation_t orig
= obj
->intern
->isolation
;
1427 zval
*zisolation
= value
;
1430 if (Z_TYPE_P(zisolation
) != IS_LONG
) {
1431 convert_to_long_ex(&zisolation
);
1434 switch ((obj
->intern
->isolation
= Z_LVAL_P(zisolation
))) {
1435 case PHP_PQTXN_READ_COMMITTED
:
1436 res
= PQexec(obj
->intern
->conn
->intern
->conn
, "SET TRANSACTION READ COMMITED");
1438 case PHP_PQTXN_REPEATABLE_READ
:
1439 res
= PQexec(obj
->intern
->conn
->intern
->conn
, "SET TRANSACTION REPEATABLE READ");
1441 case PHP_PQTXN_SERIALIZABLE
:
1442 res
= PQexec(obj
->intern
->conn
->intern
->conn
, "SET TRANSACTION SERIALIZABLE");
1445 obj
->intern
->isolation
= orig
;
1450 if (zisolation
!= value
) {
1451 zval_ptr_dtor(&zisolation
);
1455 php_pqres_success(res TSRMLS_CC
);
1460 static void php_pqtxn_object_write_readonly(zval
*object
, void *o
, zval
*value TSRMLS_DC
)
1462 php_pqtxn_object_t
*obj
= o
;
1465 if ((obj
->intern
->readonly
= zend_is_true(value
))) {
1466 res
= PQexec(obj
->intern
->conn
->intern
->conn
, "SET TRANSACTION READ ONLY");
1468 res
= PQexec(obj
->intern
->conn
->intern
->conn
, "SET TRANSACTION READ WRITE");
1472 php_pqres_success(res TSRMLS_CC
);
1477 static void php_pqtxn_object_write_deferrable(zval
*object
, void *o
, zval
*value TSRMLS_DC
)
1479 php_pqtxn_object_t
*obj
= o
;
1482 if ((obj
->intern
->deferrable
= zend_is_true(value
))) {
1483 res
= PQexec(obj
->intern
->conn
->intern
->conn
, "SET TRANSACTION DEFERRABLE");
1485 res
= PQexec(obj
->intern
->conn
->intern
->conn
, "SET TRANSACTION NOT DEFERRABLE");
1489 php_pqres_success(res TSRMLS_CC
);
1494 static void php_pqcancel_object_read_connection(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1496 php_pqcancel_object_t
*obj
= o
;
1498 php_pq_object_to_zval(obj
->intern
->conn
, &return_value TSRMLS_CC
);
1501 static void php_pqevent_object_read_connection(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1503 php_pqevent_object_t
*obj
= o
;
1505 php_pq_object_to_zval(obj
->intern
->conn
, &return_value TSRMLS_CC
);
1508 static void php_pqevent_object_read_type(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1510 php_pqevent_object_t
*obj
= o
;
1512 RETVAL_STRING(obj
->intern
->type
, 1);
1515 static void php_pqlob_object_read_transaction(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1517 php_pqlob_object_t
*obj
= o
;
1519 php_pq_object_to_zval(obj
->intern
->txn
, &return_value TSRMLS_CC
);
1522 static void php_pqlob_object_read_oid(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1524 php_pqlob_object_t
*obj
= o
;
1526 RETVAL_LONG(obj
->intern
->loid
);
1529 static void php_pqcopy_object_read_connection(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1531 php_pqcopy_object_t
*obj
= o
;
1533 php_pq_object_to_zval(obj
->intern
->conn
, &return_value TSRMLS_CC
);
1536 static void php_pqcopy_object_read_direction(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1538 php_pqcopy_object_t
*obj
= o
;
1540 RETVAL_LONG(obj
->intern
->direction
);
1543 static void php_pqcopy_object_read_expression(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1545 php_pqcopy_object_t
*obj
= o
;
1547 RETURN_STRING(obj
->intern
->expression
, 1);
1550 static void php_pqcopy_object_read_options(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
1552 php_pqcopy_object_t
*obj
= o
;
1554 RETURN_STRING(obj
->intern
->options
, 1);
1557 static zend_class_entry
*ancestor(zend_class_entry
*ce
) {
1558 while (ce
->parent
) {
1564 static zval
*php_pq_object_read_prop(zval
*object
, zval
*member
, int type
, const zend_literal
*key TSRMLS_DC
)
1566 php_pq_object_t
*obj
= zend_object_store_get_object(object TSRMLS_CC
);
1567 php_pq_object_prophandler_t
*handler
;
1571 zend_error(E_WARNING
, "%s not initialized", ancestor(obj
->zo
.ce
)->name
);
1572 } else if ((SUCCESS
== zend_hash_find(obj
->prophandler
, Z_STRVAL_P(member
), Z_STRLEN_P(member
)+1, (void *) &handler
)) && handler
->read
) {
1573 if (type
== BP_VAR_R
) {
1574 ALLOC_ZVAL(return_value
);
1575 Z_SET_REFCOUNT_P(return_value
, 0);
1576 Z_UNSET_ISREF_P(return_value
);
1578 handler
->read(object
, obj
, return_value TSRMLS_CC
);
1580 zend_error(E_ERROR
, "Cannot access %s properties by reference or array key/index", ancestor(obj
->zo
.ce
)->name
);
1581 return_value
= NULL
;
1584 return_value
= zend_get_std_object_handlers()->read_property(object
, member
, type
, key TSRMLS_CC
);
1587 return return_value
;
1590 static void php_pq_object_write_prop(zval
*object
, zval
*member
, zval
*value
, const zend_literal
*key TSRMLS_DC
)
1592 php_pq_object_t
*obj
= zend_object_store_get_object(object TSRMLS_CC
);
1593 php_pq_object_prophandler_t
*handler
;
1595 if (SUCCESS
== zend_hash_find(obj
->prophandler
, Z_STRVAL_P(member
), Z_STRLEN_P(member
)+1, (void *) &handler
)) {
1596 if (handler
->write
) {
1597 handler
->write(object
, obj
, value TSRMLS_CC
);
1600 zend_get_std_object_handlers()->write_property(object
, member
, value
, key TSRMLS_CC
);
1604 static STATUS
php_pqconn_update_socket(zval
*this_ptr
, php_pqconn_object_t
*obj TSRMLS_DC
)
1606 zval
*zsocket
, zmember
;
1612 obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1615 INIT_PZVAL(&zmember
);
1616 ZVAL_STRINGL(&zmember
, "socket", sizeof("socket")-1, 0);
1617 MAKE_STD_ZVAL(zsocket
);
1619 if ((CONNECTION_BAD
!= PQstatus(obj
->intern
->conn
))
1620 && (-1 < (socket
= PQsocket(obj
->intern
->conn
)))
1621 && (stream
= php_stream_fopen_from_fd(socket
, "r+b", NULL
))) {
1622 stream
->flags
|= PHP_STREAM_FLAG_NO_CLOSE
;
1623 php_stream_to_zval(stream
, zsocket
);
1629 zend_get_std_object_handlers()->write_property(getThis(), &zmember
, zsocket
, NULL TSRMLS_CC
);
1630 zval_ptr_dtor(&zsocket
);
1636 # define TSRMLS_DF(d) TSRMLS_D = (d)->ts
1637 # define TSRMLS_CF(d) (d)->ts = TSRMLS_C
1639 # define TSRMLS_DF(d)
1640 # define TSRMLS_CF(d)
1643 static int apply_event(void *p
, void *a TSRMLS_DC
)
1647 zval
*retval
= NULL
;
1649 zend_call_method_with_1_params(evh
, Z_OBJCE_PP(evh
), NULL
, "trigger", &retval
, args
);
1651 zval_ptr_dtor(&retval
);
1654 return ZEND_HASH_APPLY_KEEP
;
1657 static void php_pqconn_event_connreset(PGEventConnReset
*event
)
1659 php_pqconn_event_data_t
*data
= PQinstanceData(event
->conn
, php_pqconn_event
);
1665 if (SUCCESS
== zend_hash_find(&data
->obj
->intern
->eventhandlers
, ZEND_STRS("reset"), (void *) &evhs
)) {
1666 zval
*args
, *connection
= NULL
;
1668 MAKE_STD_ZVAL(args
);
1670 php_pq_object_to_zval(data
->obj
, &connection TSRMLS_CC
);
1671 add_next_index_zval(args
, connection
);
1672 zend_hash_apply_with_argument(Z_ARRVAL_PP(evhs
), apply_event
, args TSRMLS_CC
);
1673 zval_ptr_dtor(&args
);
1678 static zval
*result_instance_zval(PGresult
*res TSRMLS_DC
)
1680 zval
*rid
= PQresultInstanceData(res
, php_pqconn_event
);
1683 php_pqres_t
*r
= ecalloc(1, sizeof(*r
));
1687 ZEND_INIT_SYMTABLE(&r
->bound
);
1688 rid
->type
= IS_OBJECT
;
1689 rid
->value
.obj
= php_pqres_create_object_ex(php_pqres_class_entry
, r
, NULL TSRMLS_CC
);
1691 PQresultSetInstanceData(res
, php_pqconn_event
, rid
);
1698 static void php_pqconn_event_resultcreate(PGEventResultCreate
*event
)
1700 php_pqconn_event_data_t
*data
= PQinstanceData(event
->conn
, php_pqconn_event
);
1706 /* event listener */
1707 if (SUCCESS
== zend_hash_find(&data
->obj
->intern
->eventhandlers
, ZEND_STRS("result"), (void *) &evhs
)) {
1708 zval
*args
, *connection
= NULL
, *res
= result_instance_zval(event
->result TSRMLS_CC
);
1710 MAKE_STD_ZVAL(args
);
1712 php_pq_object_to_zval(data
->obj
, &connection TSRMLS_CC
);
1713 add_next_index_zval(args
, connection
);
1714 add_next_index_zval(args
, res
);
1715 zend_hash_apply_with_argument(Z_ARRVAL_PP(evhs
), apply_event
, args TSRMLS_CC
);
1716 zval_ptr_dtor(&args
);
1719 /* async callback */
1720 if (data
->obj
->intern
->onevent
.fci
.size
> 0) {
1721 zval
*res
= result_instance_zval(event
->result TSRMLS_CC
);
1723 zend_fcall_info_argn(&data
->obj
->intern
->onevent
.fci TSRMLS_CC
, 1, &res
);
1724 zend_fcall_info_call(&data
->obj
->intern
->onevent
.fci
, &data
->obj
->intern
->onevent
.fcc
, NULL
, NULL TSRMLS_CC
);
1725 zval_ptr_dtor(&res
);
1730 static int php_pqconn_event(PGEventId id
, void *e
, void *data
)
1733 case PGEVT_CONNRESET
:
1734 php_pqconn_event_connreset(e
);
1736 case PGEVT_RESULTCREATE
:
1737 php_pqconn_event_resultcreate(e
);
1746 static php_pqconn_event_data_t
*php_pqconn_event_data_init(php_pqconn_object_t
*obj TSRMLS_DC
)
1748 php_pqconn_event_data_t
*data
= emalloc(sizeof(*data
));
1756 static void php_pqconn_notice_recv(void *p
, const PGresult
*res
)
1758 php_pqconn_event_data_t
*data
= p
;
1762 if (SUCCESS
== zend_hash_find(&data
->obj
->intern
->eventhandlers
, ZEND_STRS("notice"), (void *) &evhs
)) {
1763 zval
*args
, *connection
= NULL
;
1765 MAKE_STD_ZVAL(args
);
1767 php_pq_object_to_zval(data
->obj
, &connection TSRMLS_CC
);
1768 add_next_index_zval(args
, connection
);
1769 add_next_index_string(args
, PHP_PQresultErrorMessage(res
), 1);
1770 zend_hash_apply_with_argument(Z_ARRVAL_PP(evhs
), apply_event
, args TSRMLS_CC
);
1771 zval_ptr_dtor(&args
);
1775 typedef struct php_pqconn_resource_factory_data
{
1778 } php_pqconn_resource_factory_data_t
;
1780 static void *php_pqconn_resource_factory_ctor(void *data
, void *init_arg TSRMLS_DC
)
1782 php_pqconn_resource_factory_data_t
*o
= init_arg
;
1784 if (o
->flags
& PHP_PQCONN_ASYNC
) {
1785 return PQconnectStart(o
->dsn
);
1787 return PQconnectdb(o
->dsn
);
1791 static void php_pqconn_resource_factory_dtor(void *opaque
, void *handle TSRMLS_DC
)
1796 static php_resource_factory_ops_t php_pqconn_resource_factory_ops
= {
1797 php_pqconn_resource_factory_ctor
,
1799 php_pqconn_resource_factory_dtor
1802 static void php_pqconn_persistent_resource_factory_dtor(void *opaque
, void *handle TSRMLS_DC
)
1808 if ((res
= PQexec(handle
, PQtransactionStatus(handle
) == PQTRANS_IDLE
? "RESET ALL" : "ROLLBACK; RESET ALL"))) {
1812 /* release to the pool, if the connection is alive */
1813 if (CONNECTION_OK
== PQstatus(handle
)) {
1814 php_persistent_handle_release(opaque
, handle TSRMLS_CC
);
1820 static php_resource_factory_ops_t php_pqconn_persistent_resource_factory_ops
= {
1821 (php_resource_factory_handle_ctor_t
) php_persistent_handle_acquire
,
1823 php_pqconn_persistent_resource_factory_dtor
1826 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_construct
, 0, 0, 1)
1827 ZEND_ARG_INFO(0, dsn
)
1828 ZEND_ARG_INFO(0, async
)
1829 ZEND_END_ARG_INFO();
1830 static PHP_METHOD(pqconn
, __construct
) {
1831 zend_error_handling zeh
;
1836 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
1837 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|sl", &dsn_str
, &dsn_len
, &flags
)) {
1838 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1839 php_pqconn_event_data_t
*evdata
= php_pqconn_event_data_init(obj TSRMLS_CC
);
1840 php_pqconn_resource_factory_data_t rfdata
= {dsn_str
, flags
};
1842 obj
->intern
= ecalloc(1, sizeof(*obj
->intern
));
1844 zend_hash_init(&obj
->intern
->listeners
, 0, NULL
, (dtor_func_t
) zend_hash_destroy
, 0);
1845 zend_hash_init(&obj
->intern
->eventhandlers
, 0, NULL
, ZVAL_PTR_DTOR
, 0);
1847 if (flags
& PHP_PQCONN_PERSISTENT
) {
1848 php_persistent_handle_factory_t
*phf
= php_persistent_handle_concede(NULL
, ZEND_STRL("pq\\Connection"), dsn_str
, dsn_len TSRMLS_CC
);
1849 php_resource_factory_init(&obj
->intern
->factory
, &php_pqconn_persistent_resource_factory_ops
, phf
, (void (*)(void*)) php_persistent_handle_abandon
);
1851 php_resource_factory_init(&obj
->intern
->factory
, &php_pqconn_resource_factory_ops
, NULL
, NULL
);
1853 if (flags
& PHP_PQCONN_ASYNC
) {
1854 obj
->intern
->poller
= (int (*)(PGconn
*)) PQconnectPoll
;
1857 obj
->intern
->conn
= php_resource_factory_handle_ctor(&obj
->intern
->factory
, &rfdata TSRMLS_CC
);
1859 PQregisterEventProc(obj
->intern
->conn
, php_pqconn_event
, "ext-pq", NULL
);
1860 /* the connection might be persistent, so reset event_proc instance data */
1861 PQsetInstanceData(obj
->intern
->conn
, php_pqconn_event
, evdata
);
1862 PQsetNoticeReceiver(obj
->intern
->conn
, php_pqconn_notice_recv
, evdata
);
1864 if (SUCCESS
!= php_pqconn_update_socket(getThis(), obj TSRMLS_CC
)) {
1865 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Connection failed (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
1868 zend_restore_error_handling(&zeh TSRMLS_CC
);
1871 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_reset
, 0, 0, 0)
1872 ZEND_END_ARG_INFO();
1873 static PHP_METHOD(pqconn
, reset
) {
1874 if (SUCCESS
== zend_parse_parameters_none()) {
1875 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1878 PQreset(obj
->intern
->conn
);
1880 if (CONNECTION_OK
== PQstatus(obj
->intern
->conn
)) {
1883 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Connection reset failed: (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
1886 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
1892 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_reset_async
, 0, 0, 0)
1893 ZEND_END_ARG_INFO();
1894 static PHP_METHOD(pqconn
, resetAsync
) {
1895 if (SUCCESS
== zend_parse_parameters_none()) {
1896 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1899 if (PQresetStart(obj
->intern
->conn
)) {
1900 obj
->intern
->poller
= (int (*)(PGconn
*)) PQresetPoll
;
1904 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
1910 static void php_pqconn_add_listener(php_pqconn_object_t
*obj
, const char *channel_str
, size_t channel_len
, php_pq_callback_t
*listener TSRMLS_DC
)
1912 HashTable ht
, *existing_listeners
;
1914 php_pq_callback_addref(listener
);
1916 if (SUCCESS
== zend_hash_find(&obj
->intern
->listeners
, channel_str
, channel_len
+ 1, (void *) &existing_listeners
)) {
1917 zend_hash_next_index_insert(existing_listeners
, (void *) listener
, sizeof(*listener
), NULL
);
1919 zend_hash_init(&ht
, 1, NULL
, (dtor_func_t
) php_pq_callback_dtor
, 0);
1920 zend_hash_next_index_insert(&ht
, (void *) listener
, sizeof(*listener
), NULL
);
1921 zend_hash_add(&obj
->intern
->listeners
, channel_str
, channel_len
+ 1, (void *) &ht
, sizeof(HashTable
), NULL
);
1925 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_listen
, 0, 0, 0)
1926 ZEND_ARG_INFO(0, channel
)
1927 ZEND_ARG_INFO(0, callable
)
1928 ZEND_END_ARG_INFO();
1929 static PHP_METHOD(pqconn
, listen
) {
1930 char *channel_str
= NULL
;
1931 int channel_len
= 0;
1932 php_pq_callback_t listener
;
1934 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "sf", &channel_str
, &channel_len
, &listener
.fci
, &listener
.fcc
)) {
1935 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1937 obj
->intern
->poller
= PQconsumeInput
;
1940 char *quoted_channel
= PQescapeIdentifier(obj
->intern
->conn
, channel_str
, channel_len
);
1942 if (quoted_channel
) {
1946 spprintf(&cmd
, 0, "LISTEN %s", quoted_channel
);
1947 res
= PQexec(obj
->intern
->conn
, cmd
);
1950 PQfreemem(quoted_channel
);
1953 if (SUCCESS
== php_pqres_success(res TSRMLS_CC
)) {
1954 php_pqconn_add_listener(obj
, channel_str
, channel_len
, &listener TSRMLS_CC
);
1961 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not install listener (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
1965 php_pqconn_notify_listeners(obj TSRMLS_CC
);
1967 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not escape channel identifier (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
1970 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
1976 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_listen_async
, 0, 0, 0)
1977 ZEND_ARG_INFO(0, channel
)
1978 ZEND_ARG_INFO(0, callable
)
1979 ZEND_END_ARG_INFO();
1980 static PHP_METHOD(pqconn
, listenAsync
) {
1981 char *channel_str
= NULL
;
1982 int channel_len
= 0;
1983 php_pq_callback_t listener
;
1985 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "sf", &channel_str
, &channel_len
, &listener
.fci
, &listener
.fcc
)) {
1986 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1988 obj
->intern
->poller
= PQconsumeInput
;
1991 char *quoted_channel
= PQescapeIdentifier(obj
->intern
->conn
, channel_str
, channel_len
);
1993 if (quoted_channel
) {
1996 obj
->intern
->poller
= PQconsumeInput
;
1998 spprintf(&cmd
, 0, "LISTEN %s", channel_str
);
1999 if (PQsendQuery(obj
->intern
->conn
, cmd
)) {
2000 php_pqconn_add_listener(obj
, channel_str
, channel_len
, &listener TSRMLS_CC
);
2003 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not install listener (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
2008 PQfreemem(quoted_channel
);
2010 php_pqconn_notify_listeners(obj TSRMLS_CC
);
2012 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not escape channel identifier (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
2015 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
2021 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_notify
, 0, 0, 2)
2022 ZEND_ARG_INFO(0, channel
)
2023 ZEND_ARG_INFO(0, message
)
2024 ZEND_END_ARG_INFO();
2025 static PHP_METHOD(pqconn
, notify
) {
2026 char *channel_str
, *message_str
;
2027 int channel_len
, message_len
;
2029 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "ss", &channel_str
, &channel_len
, &message_str
, &message_len
)) {
2030 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2034 char *params
[2] = {channel_str
, message_str
};
2036 res
= PQexecParams(obj
->intern
->conn
, "select pg_notify($1, $2)", 2, NULL
, (const char *const*) params
, NULL
, NULL
, 0);
2039 if (SUCCESS
== php_pqres_success(res TSRMLS_CC
)) {
2046 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not notify listeners (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
2050 php_pqconn_notify_listeners(obj TSRMLS_CC
);
2053 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
2059 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_notify_async
, 0, 0, 2)
2060 ZEND_ARG_INFO(0, channel
)
2061 ZEND_ARG_INFO(0, message
)
2062 ZEND_END_ARG_INFO();
2063 static PHP_METHOD(pqconn
, notifyAsync
) {
2064 char *channel_str
, *message_str
;
2065 int channel_len
, message_len
;
2067 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "ss", &channel_str
, &channel_len
, &message_str
, &message_len
)) {
2068 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2071 char *params
[2] = {channel_str
, message_str
};
2073 obj
->intern
->poller
= PQconsumeInput
;
2075 if (PQsendQueryParams(obj
->intern
->conn
, "select pg_notify($1, $2)", 2, NULL
, (const char *const*) params
, NULL
, NULL
, 0)) {
2078 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not notify listeners (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
2082 php_pqconn_notify_listeners(obj TSRMLS_CC
);
2085 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
2091 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_poll
, 0, 0, 0)
2092 ZEND_END_ARG_INFO();
2093 static PHP_METHOD(pqconn
, poll
) {
2094 if (SUCCESS
== zend_parse_parameters_none()) {
2095 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2098 if (obj
->intern
->poller
) {
2099 if (obj
->intern
->poller
== PQconsumeInput
) {
2100 RETVAL_LONG(obj
->intern
->poller(obj
->intern
->conn
) * PGRES_POLLING_OK
);
2101 php_pqconn_notify_listeners(obj TSRMLS_CC
);
2104 RETURN_LONG(obj
->intern
->poller(obj
->intern
->conn
));
2107 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "No asynchronous operation active");
2110 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
2116 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec
, 0, 0, 1)
2117 ZEND_ARG_INFO(0, query
)
2118 ZEND_END_ARG_INFO();
2119 static PHP_METHOD(pqconn
, exec
) {
2120 zend_error_handling zeh
;
2124 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
2125 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &query_str
, &query_len
)) {
2126 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2129 PGresult
*res
= PQexec(obj
->intern
->conn
, query_str
);
2131 php_pqconn_notify_listeners(obj TSRMLS_CC
);
2134 if (SUCCESS
== php_pqres_success(res TSRMLS_CC
)) {
2135 php_pqres_t
*r
= ecalloc(1, sizeof(*r
));
2138 ZEND_INIT_SYMTABLE(&r
->bound
);
2139 return_value
->type
= IS_OBJECT
;
2140 return_value
->value
.obj
= php_pqres_create_object_ex(php_pqres_class_entry
, r
, NULL TSRMLS_CC
);
2143 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not execute query (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
2146 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
2149 zend_restore_error_handling(&zeh TSRMLS_CC
);
2152 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_get_result
, 0, 0, 0)
2153 ZEND_END_ARG_INFO();
2154 static PHP_METHOD(pqconn
, getResult
) {
2155 if (SUCCESS
== zend_parse_parameters_none()) {
2156 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2159 PGresult
*res
= PQgetResult(obj
->intern
->conn
);
2162 php_pqres_t
*r
= ecalloc(1, sizeof(*r
));
2165 ZEND_INIT_SYMTABLE(&r
->bound
);
2166 return_value
->type
= IS_OBJECT
;
2167 return_value
->value
.obj
= php_pqres_create_object_ex(php_pqres_class_entry
, r
, NULL TSRMLS_CC
);
2172 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
2178 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_async
, 0, 0, 1)
2179 ZEND_ARG_INFO(0, query
)
2180 ZEND_ARG_INFO(0, callable
)
2181 ZEND_END_ARG_INFO();
2182 static PHP_METHOD(pqconn
, execAsync
) {
2183 zend_error_handling zeh
;
2184 php_pq_callback_t resolver
= {{0}};
2188 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
2189 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s|f", &query_str
, &query_len
, &resolver
.fci
, &resolver
.fcc
)) {
2190 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2193 php_pq_callback_dtor(&obj
->intern
->onevent
);
2194 if (resolver
.fci
.size
> 0) {
2195 obj
->intern
->onevent
= resolver
;
2196 php_pq_callback_addref(&obj
->intern
->onevent
);
2199 obj
->intern
->poller
= PQconsumeInput
;
2201 if (PQsendQuery(obj
->intern
->conn
, query_str
)) {
2202 if (obj
->intern
->unbuffered
) {
2203 if (!PQsetSingleRowMode(obj
->intern
->conn
)) {
2204 php_error_docref(NULL TSRMLS_CC
, E_NOTICE
, "Could not enable unbuffered mode (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
2209 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not execute query (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
2213 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
2217 zend_restore_error_handling(&zeh TSRMLS_CC
);
2220 static int apply_to_oid(void *p
, void *arg TSRMLS_DC
)
2225 if (Z_TYPE_PP(ztype
) != IS_LONG
) {
2226 convert_to_long_ex(ztype
);
2229 **types
= Z_LVAL_PP(ztype
);
2232 if (*ztype
!= *(zval
**)p
) {
2233 zval_ptr_dtor(ztype
);
2235 return ZEND_HASH_APPLY_KEEP
;
2238 static int apply_to_param(void *p TSRMLS_DC
, int argc
, va_list argv
, zend_hash_key
*key
)
2244 params
= (char ***) va_arg(argv
, char ***);
2245 zdtor
= (HashTable
*) va_arg(argv
, HashTable
*);
2247 if (Z_TYPE_PP(zparam
) == IS_NULL
) {
2251 if (Z_TYPE_PP(zparam
) != IS_STRING
) {
2252 convert_to_string_ex(zparam
);
2255 **params
= Z_STRVAL_PP(zparam
);
2258 if (*zparam
!= *(zval
**)p
) {
2259 zend_hash_next_index_insert(zdtor
, zparam
, sizeof(zval
*), NULL
);
2262 return ZEND_HASH_APPLY_KEEP
;
2265 static int php_pq_types_to_array(HashTable
*ht
, Oid
**types TSRMLS_DC
)
2267 int count
= zend_hash_num_elements(ht
);
2274 /* +1 for when less types than params are specified */
2275 *types
= tmp
= ecalloc(count
+ 1, sizeof(Oid
));
2276 zend_hash_apply_with_argument(ht
, apply_to_oid
, &tmp TSRMLS_CC
);
2282 static int php_pq_params_to_array(HashTable
*ht
, char ***params
, HashTable
*zdtor TSRMLS_DC
)
2284 int count
= zend_hash_num_elements(ht
);
2291 *params
= tmp
= ecalloc(count
, sizeof(char *));
2292 zend_hash_apply_with_arguments(ht TSRMLS_CC
, apply_to_param
, 2, &tmp
, zdtor
);
2298 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_params
, 0, 0, 2)
2299 ZEND_ARG_INFO(0, query
)
2300 ZEND_ARG_ARRAY_INFO(0, params
, 0)
2301 ZEND_ARG_ARRAY_INFO(0, types
, 1)
2302 ZEND_END_ARG_INFO();
2303 static PHP_METHOD(pqconn
, execParams
) {
2304 zend_error_handling zeh
;
2308 zval
*ztypes
= NULL
;
2310 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
2311 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "sa/|a/!", &query_str
, &query_len
, &zparams
, &ztypes
)) {
2312 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2318 char **params
= NULL
;
2321 ZEND_INIT_SYMTABLE(&zdtor
);
2322 count
= php_pq_params_to_array(Z_ARRVAL_P(zparams
), ¶ms
, &zdtor TSRMLS_CC
);
2325 php_pq_types_to_array(Z_ARRVAL_P(ztypes
), &types TSRMLS_CC
);
2328 res
= PQexecParams(obj
->intern
->conn
, query_str
, count
, types
, (const char *const*) params
, NULL
, NULL
, 0);
2330 zend_hash_destroy(&zdtor
);
2338 php_pqconn_notify_listeners(obj TSRMLS_CC
);
2341 if (SUCCESS
== php_pqres_success(res TSRMLS_CC
)) {
2342 php_pqres_t
*r
= ecalloc(1, sizeof(*r
));
2345 ZEND_INIT_SYMTABLE(&r
->bound
);
2346 return_value
->type
= IS_OBJECT
;
2347 return_value
->value
.obj
= php_pqres_create_object_ex(php_pqres_class_entry
, r
, NULL TSRMLS_CC
);
2350 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not execute query (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
2354 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
2358 zend_restore_error_handling(&zeh TSRMLS_CC
);
2361 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_params_async
, 0, 0, 2)
2362 ZEND_ARG_INFO(0, query
)
2363 ZEND_ARG_ARRAY_INFO(0, params
, 0)
2364 ZEND_ARG_ARRAY_INFO(0, types
, 1)
2365 ZEND_ARG_INFO(0, callable
)
2366 ZEND_END_ARG_INFO();
2367 static PHP_METHOD(pqconn
, execParamsAsync
) {
2368 zend_error_handling zeh
;
2369 php_pq_callback_t resolver
= {{0}};
2373 zval
*ztypes
= NULL
;
2375 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
2376 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "sa/|a/!f", &query_str
, &query_len
, &zparams
, &ztypes
, &resolver
.fci
, &resolver
.fcc
)) {
2377 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2382 char **params
= NULL
;
2385 ZEND_INIT_SYMTABLE(&zdtor
);
2386 count
= php_pq_params_to_array(Z_ARRVAL_P(zparams
), ¶ms
, &zdtor TSRMLS_CC
);
2389 php_pq_types_to_array(Z_ARRVAL_P(ztypes
), &types TSRMLS_CC
);
2392 php_pq_callback_dtor(&obj
->intern
->onevent
);
2393 if (resolver
.fci
.size
> 0) {
2394 obj
->intern
->onevent
= resolver
;
2395 php_pq_callback_addref(&obj
->intern
->onevent
);
2398 obj
->intern
->poller
= PQconsumeInput
;
2400 if (PQsendQueryParams(obj
->intern
->conn
, query_str
, count
, types
, (const char *const*) params
, NULL
, NULL
, 0)) {
2401 if (obj
->intern
->unbuffered
) {
2402 if (!PQsetSingleRowMode(obj
->intern
->conn
)) {
2403 php_error_docref(NULL TSRMLS_CC
, E_NOTICE
, "Could not enable unbuffered mode (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
2408 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not execute query (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
2412 zend_hash_destroy(&zdtor
);
2420 php_pqconn_notify_listeners(obj TSRMLS_CC
);
2423 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
2427 zend_restore_error_handling(&zeh TSRMLS_CC
);
2430 static STATUS
php_pqconn_prepare(zval
*object
, php_pqconn_object_t
*obj
, const char *name
, const char *query
, HashTable
*typest TSRMLS_DC
)
2438 obj
= zend_object_store_get_object(object TSRMLS_CC
);
2442 count
= zend_hash_num_elements(typest
);
2443 php_pq_types_to_array(typest
, &types TSRMLS_CC
);
2446 res
= PQprepare(obj
->intern
->conn
, name
, query
, count
, types
);
2453 rv
= php_pqres_success(res TSRMLS_CC
);
2457 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not prepare statement (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
2463 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_prepare
, 0, 0, 2)
2464 ZEND_ARG_INFO(0, type
)
2465 ZEND_ARG_INFO(0, query
)
2466 ZEND_ARG_ARRAY_INFO(0, types
, 1)
2467 ZEND_END_ARG_INFO();
2468 static PHP_METHOD(pqconn
, prepare
) {
2469 zend_error_handling zeh
;
2470 zval
*ztypes
= NULL
;
2471 char *name_str
, *query_str
;
2472 int name_len
, *query_len
;
2474 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
2475 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "ss|a/!", &name_str
, &name_len
, &query_str
, &query_len
, &ztypes
)) {
2476 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2479 if (SUCCESS
== php_pqconn_prepare(getThis(), obj
, name_str
, query_str
, ztypes
? Z_ARRVAL_P(ztypes
) : NULL TSRMLS_CC
)) {
2480 php_pqstm_t
*stm
= ecalloc(1, sizeof(*stm
));
2482 php_pq_object_addref(obj TSRMLS_CC
);
2484 stm
->name
= estrdup(name_str
);
2485 ZEND_INIT_SYMTABLE(&stm
->bound
);
2487 return_value
->type
= IS_OBJECT
;
2488 return_value
->value
.obj
= php_pqstm_create_object_ex(php_pqstm_class_entry
, stm
, NULL TSRMLS_CC
);
2490 php_pqconn_notify_listeners(obj TSRMLS_CC
);
2492 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
2495 zend_restore_error_handling(&zeh TSRMLS_CC
);
2498 static STATUS
php_pqconn_prepare_async(zval
*object
, php_pqconn_object_t
*obj
, const char *name
, const char *query
, HashTable
*typest TSRMLS_DC
)
2505 obj
= zend_object_store_get_object(object TSRMLS_CC
);
2509 count
= php_pq_types_to_array(typest
, &types TSRMLS_CC
);
2512 if (PQsendPrepare(obj
->intern
->conn
, name
, query
, count
, types
)) {
2513 if (obj
->intern
->unbuffered
) {
2514 if (!PQsetSingleRowMode(obj
->intern
->conn
)) {
2515 php_error_docref(NULL TSRMLS_CC
, E_NOTICE
, "Could not enable unbuffered mode (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
2520 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not prepare statement (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
2531 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_prepare_async
, 0, 0, 2)
2532 ZEND_ARG_INFO(0, type
)
2533 ZEND_ARG_INFO(0, query
)
2534 ZEND_ARG_ARRAY_INFO(0, types
, 1)
2535 ZEND_END_ARG_INFO();
2536 static PHP_METHOD(pqconn
, prepareAsync
) {
2537 zend_error_handling zeh
;
2538 zval
*ztypes
= NULL
;
2539 char *name_str
, *query_str
;
2540 int name_len
, *query_len
;
2542 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
2543 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "ss|a/!", &name_str
, &name_len
, &query_str
, &query_len
, &ztypes
)) {
2544 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2547 obj
->intern
->poller
= PQconsumeInput
;
2548 if (SUCCESS
== php_pqconn_prepare_async(getThis(), obj
, name_str
, query_str
, ztypes
? Z_ARRVAL_P(ztypes
) : NULL TSRMLS_CC
)) {
2549 php_pqstm_t
*stm
= ecalloc(1, sizeof(*stm
));
2551 php_pq_object_addref(obj TSRMLS_CC
);
2553 stm
->name
= estrdup(name_str
);
2554 ZEND_INIT_SYMTABLE(&stm
->bound
);
2556 return_value
->type
= IS_OBJECT
;
2557 return_value
->value
.obj
= php_pqstm_create_object_ex(php_pqstm_class_entry
, stm
, NULL TSRMLS_CC
);
2559 php_pqconn_notify_listeners(obj TSRMLS_CC
);
2561 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
2564 zend_restore_error_handling(&zeh TSRMLS_CC
);
2567 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_quote
, 0, 0, 1)
2568 ZEND_ARG_INFO(0, string
)
2569 ZEND_END_ARG_INFO();
2570 static PHP_METHOD(pqconn
, quote
) {
2574 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &str
, &len
)) {
2575 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2578 char *quoted
= PQescapeLiteral(obj
->intern
->conn
, str
, len
);
2581 RETVAL_STRING(quoted
, 1);
2584 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not quote string (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
2588 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
2594 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_quote_name
, 0, 0, 1)
2595 ZEND_ARG_INFO(0, type
)
2596 ZEND_END_ARG_INFO();
2597 static PHP_METHOD(pqconn
, quoteName
) {
2601 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &str
, &len
)) {
2602 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2605 char *quoted
= PQescapeIdentifier(obj
->intern
->conn
, str
, len
);
2608 RETVAL_STRING(quoted
, 1);
2611 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not quote name (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
2615 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
2621 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_escape_bytea
, 0, 0, 1)
2622 ZEND_ARG_INFO(0, bytea
)
2623 ZEND_END_ARG_INFO();
2624 static PHP_METHOD(pqconn
, escapeBytea
) {
2628 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &str
, &len
)) {
2629 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2633 char *escaped_str
= (char *) PQescapeByteaConn(obj
->intern
->conn
, (unsigned char *) str
, len
, &escaped_len
);
2636 RETVAL_STRINGL(escaped_str
, escaped_len
- 1, 1);
2637 PQfreemem(escaped_str
);
2639 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not escape bytea (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
2643 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
2649 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_unescape_bytea
, 0, 0, 1)
2650 ZEND_ARG_INFO(0, bytea
)
2651 ZEND_END_ARG_INFO();
2652 static PHP_METHOD(pqconn
, unescapeBytea
) {
2656 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &str
, &len
)) {
2657 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2660 size_t unescaped_len
;
2661 char *unescaped_str
= (char *) PQunescapeBytea((unsigned char *)str
, &unescaped_len
);
2663 if (unescaped_str
) {
2664 RETVAL_STRINGL(unescaped_str
, unescaped_len
, 1);
2665 PQfreemem(unescaped_str
);
2667 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not unescape bytea (%s)", PHP_PQerrorMessage(obj
->intern
->conn
));
2671 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
2677 static const char *isolation_level(long *isolation
) {
2678 switch (*isolation
) {
2679 case PHP_PQTXN_SERIALIZABLE
:
2680 return "SERIALIZABLE";
2681 case PHP_PQTXN_REPEATABLE_READ
:
2682 return "REPEATABLE READ";
2684 *isolation
= PHP_PQTXN_READ_COMMITTED
;
2686 case PHP_PQTXN_READ_COMMITTED
:
2687 return "READ COMMITTED";
2691 static STATUS
php_pqconn_start_transaction(zval
*zconn
, php_pqconn_object_t
*conn_obj
, long isolation
, zend_bool readonly
, zend_bool deferrable TSRMLS_DC
)
2694 conn_obj
= zend_object_store_get_object(zconn TSRMLS_CC
);
2697 if (conn_obj
->intern
) {
2701 spprintf(&cmd
, 0, "START TRANSACTION ISOLATION LEVEL %s, READ %s, %s DEFERRABLE",
2702 isolation_level(&isolation
), readonly
? "ONLY" : "WRITE", deferrable
? "": "NOT");
2704 res
= PQexec(conn_obj
->intern
->conn
, cmd
);
2709 STATUS rv
= php_pqres_success(res TSRMLS_CC
);
2714 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not start transaction (%s)", PHP_PQerrorMessage(conn_obj
->intern
->conn
));
2718 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
2723 static STATUS
php_pqconn_start_transaction_async(zval
*zconn
, php_pqconn_object_t
*conn_obj
, long isolation
, zend_bool readonly
, zend_bool deferrable TSRMLS_DC
)
2726 conn_obj
= zend_object_store_get_object(zconn TSRMLS_CC
);
2729 if (conn_obj
->intern
->conn
) {
2732 spprintf(&cmd
, 0, "START TRANSACTION ISOLATION LEVEL %s, READ %s, %s DEFERRABLE",
2733 isolation_level(&isolation
), readonly
? "ONLY" : "WRITE", deferrable
? "": "NOT");
2735 if (PQsendQuery(conn_obj
->intern
->conn
, cmd
)) {
2736 conn_obj
->intern
->poller
= PQconsumeInput
;
2741 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not start transaction (%s)", PHP_PQerrorMessage(conn_obj
->intern
->conn
));
2745 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
2750 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_start_transaction
, 0, 0, 0)
2751 ZEND_ARG_INFO(0, isolation
)
2752 ZEND_ARG_INFO(0, readonly
)
2753 ZEND_ARG_INFO(0, deferrable
)
2754 ZEND_END_ARG_INFO();
2755 static PHP_METHOD(pqconn
, startTransaction
) {
2756 zend_error_handling zeh
;
2757 long isolation
= PHP_PQTXN_READ_COMMITTED
;
2758 zend_bool readonly
= 0, deferrable
= 0;
2760 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
2761 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|lbb", &isolation
, &readonly
, &deferrable
)) {
2763 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2765 rv
= php_pqconn_start_transaction(getThis(), obj
, isolation
, readonly
, deferrable TSRMLS_CC
);
2767 if (SUCCESS
== rv
) {
2768 php_pqtxn_t
*txn
= ecalloc(1, sizeof(*txn
));
2770 php_pq_object_addref(obj TSRMLS_CC
);
2772 txn
->isolation
= isolation
;
2773 txn
->readonly
= readonly
;
2774 txn
->deferrable
= deferrable
;
2776 return_value
->type
= IS_OBJECT
;
2777 return_value
->value
.obj
= php_pqtxn_create_object_ex(php_pqtxn_class_entry
, txn
, NULL TSRMLS_CC
);
2780 zend_restore_error_handling(&zeh TSRMLS_CC
);
2784 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_start_transaction_async
, 0, 0, 0)
2785 ZEND_ARG_INFO(0, isolation
)
2786 ZEND_ARG_INFO(0, readonly
)
2787 ZEND_ARG_INFO(0, deferrable
)
2788 ZEND_END_ARG_INFO();
2789 static PHP_METHOD(pqconn
, startTransactionAsync
) {
2790 zend_error_handling zeh
;
2791 long isolation
= PHP_PQTXN_READ_COMMITTED
;
2792 zend_bool readonly
= 0, deferrable
= 0;
2794 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
2795 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|lbb", &isolation
, &readonly
, &deferrable
)) {
2797 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2799 rv
= php_pqconn_start_transaction_async(getThis(), obj
, isolation
, readonly
, deferrable TSRMLS_CC
);
2801 if (SUCCESS
== rv
) {
2802 php_pqtxn_t
*txn
= ecalloc(1, sizeof(*txn
));
2804 php_pq_object_addref(obj TSRMLS_CC
);
2806 txn
->isolation
= isolation
;
2807 txn
->readonly
= readonly
;
2808 txn
->deferrable
= deferrable
;
2810 return_value
->type
= IS_OBJECT
;
2811 return_value
->value
.obj
= php_pqtxn_create_object_ex(php_pqtxn_class_entry
, txn
, NULL TSRMLS_CC
);
2814 zend_restore_error_handling(&zeh TSRMLS_CC
);
2817 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_trace
, 0, 0, 0)
2818 ZEND_ARG_INFO(0, stdio_stream
)
2819 ZEND_END_ARG_INFO();
2820 static PHP_METHOD(pqconn
, trace
) {
2821 zval
*zstream
= NULL
;
2823 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|r!", &zstream
)) {
2824 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2828 php_stream
*stream
= NULL
;
2830 php_stream_from_zval(stream
, &zstream
);
2832 if (SUCCESS
== php_stream_cast(stream
, PHP_STREAM_AS_STDIO
, (void *) &fp
, REPORT_ERRORS
)) {
2833 stream
->flags
|= PHP_STREAM_FLAG_NO_CLOSE
;
2834 PQtrace(obj
->intern
->conn
, fp
);
2840 PQuntrace(obj
->intern
->conn
);
2844 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
2850 static zend_function_entry php_pqconn_methods
[] = {
2851 PHP_ME(pqconn
, __construct
, ai_pqconn_construct
, ZEND_ACC_PUBLIC
|ZEND_ACC_CTOR
)
2852 PHP_ME(pqconn
, reset
, ai_pqconn_reset
, ZEND_ACC_PUBLIC
)
2853 PHP_ME(pqconn
, resetAsync
, ai_pqconn_reset_async
, ZEND_ACC_PUBLIC
)
2854 PHP_ME(pqconn
, poll
, ai_pqconn_poll
, ZEND_ACC_PUBLIC
)
2855 PHP_ME(pqconn
, exec
, ai_pqconn_exec
, ZEND_ACC_PUBLIC
)
2856 PHP_ME(pqconn
, execAsync
, ai_pqconn_exec_async
, ZEND_ACC_PUBLIC
)
2857 PHP_ME(pqconn
, execParams
, ai_pqconn_exec_params
, ZEND_ACC_PUBLIC
)
2858 PHP_ME(pqconn
, execParamsAsync
, ai_pqconn_exec_params_async
, ZEND_ACC_PUBLIC
)
2859 PHP_ME(pqconn
, prepare
, ai_pqconn_prepare
, ZEND_ACC_PUBLIC
)
2860 PHP_ME(pqconn
, prepareAsync
, ai_pqconn_prepare_async
, ZEND_ACC_PUBLIC
)
2861 PHP_ME(pqconn
, listen
, ai_pqconn_listen
, ZEND_ACC_PUBLIC
)
2862 PHP_ME(pqconn
, listenAsync
, ai_pqconn_listen_async
, ZEND_ACC_PUBLIC
)
2863 PHP_ME(pqconn
, notify
, ai_pqconn_notify
, ZEND_ACC_PUBLIC
)
2864 PHP_ME(pqconn
, notifyAsync
, ai_pqconn_notify_async
, ZEND_ACC_PUBLIC
)
2865 PHP_ME(pqconn
, getResult
, ai_pqconn_get_result
, ZEND_ACC_PUBLIC
)
2866 PHP_ME(pqconn
, quote
, ai_pqconn_quote
, ZEND_ACC_PUBLIC
)
2867 PHP_ME(pqconn
, quoteName
, ai_pqconn_quote_name
, ZEND_ACC_PUBLIC
)
2868 PHP_ME(pqconn
, escapeBytea
, ai_pqconn_escape_bytea
, ZEND_ACC_PUBLIC
)
2869 PHP_ME(pqconn
, unescapeBytea
, ai_pqconn_unescape_bytea
, ZEND_ACC_PUBLIC
)
2870 PHP_ME(pqconn
, startTransaction
, ai_pqconn_start_transaction
, ZEND_ACC_PUBLIC
)
2871 PHP_ME(pqconn
, startTransactionAsync
, ai_pqconn_start_transaction_async
, ZEND_ACC_PUBLIC
)
2872 PHP_ME(pqconn
, trace
, ai_pqconn_trace
, ZEND_ACC_PUBLIC
)
2876 ZEND_BEGIN_ARG_INFO_EX(ai_pqtypes_construct
, 0, 0, 1)
2877 ZEND_ARG_OBJ_INFO(0, connection
, pq
\\Connection
, 0)
2878 ZEND_END_ARG_INFO();
2879 static PHP_METHOD(pqtypes
, __construct
) {
2880 zend_error_handling zeh
;
2883 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
2884 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "O", &zconn
, php_pqconn_class_entry
)) {
2885 php_pqconn_object_t
*conn_obj
= zend_object_store_get_object(zconn TSRMLS_CC
);
2887 if (conn_obj
->intern
) {
2888 zval
*retval
= NULL
;
2889 php_pqtypes_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2891 obj
->intern
= ecalloc(1, sizeof(*obj
->intern
));
2892 obj
->intern
->conn
= conn_obj
;
2893 php_pq_object_addref(conn_obj TSRMLS_CC
);
2894 zend_hash_init(&obj
->intern
->types
, 300, NULL
, ZVAL_PTR_DTOR
, 0);
2896 zend_call_method_with_0_params(&getThis(), Z_OBJCE_P(getThis()), NULL
, "refresh", &retval
);
2898 zval_ptr_dtor(&retval
);
2901 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Connection not initialized");
2904 zend_restore_error_handling(&zeh TSRMLS_CC
);
2907 #define PHP_PQ_TYPES_QUERY \
2908 "select t.oid, t.* " \
2909 "from pg_type t join pg_namespace n on t.typnamespace=n.oid " \
2910 "where typisdefined " \
2912 "and nspname in ('public', 'pg_catalog')"
2914 ZEND_BEGIN_ARG_INFO_EX(ai_pqtypes_refresh
, 0, 0, 0)
2915 ZEND_END_ARG_INFO();
2916 static PHP_METHOD(pqtypes
, refresh
) {
2917 if (SUCCESS
== zend_parse_parameters_none()) {
2918 php_pqtypes_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2921 PGresult
*res
= PQexec(obj
->intern
->conn
->intern
->conn
, PHP_PQ_TYPES_QUERY
);
2923 php_pqconn_notify_listeners(obj
->intern
->conn TSRMLS_CC
);
2926 if (PGRES_TUPLES_OK
== PQresultStatus(res
)) {
2929 for (r
= 0, rows
= PQntuples(res
); r
< rows
; ++r
) {
2930 zval
*row
= php_pqres_row_to_zval(res
, r
, PHP_PQRES_FETCH_OBJECT
, NULL TSRMLS_CC
);
2931 long oid
= atol(PQgetvalue(res
, r
, 0 ));
2932 char *name
= PQgetvalue(res
, r
, 1);
2936 zend_hash_index_update(&obj
->intern
->types
, oid
, (void *) &row
, sizeof(zval
*), NULL
);
2937 zend_hash_add(&obj
->intern
->types
, name
, strlen(name
) + 1, (void *) &row
, sizeof(zval
*), NULL
);
2940 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not fetch types (%s)", PHP_PQresultErrorMessage(res
));
2944 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not fetch types (%s)", PHP_PQerrorMessage(obj
->intern
->conn
->intern
->conn
));
2948 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Types not initialized");
2953 static zend_function_entry php_pqtypes_methods
[] = {
2954 PHP_ME(pqtypes
, __construct
, ai_pqtypes_construct
, ZEND_ACC_PUBLIC
|ZEND_ACC_CTOR
)
2955 PHP_ME(pqtypes
, refresh
, ai_pqtypes_refresh
, ZEND_ACC_PUBLIC
)
2959 static STATUS
php_pqres_iteration(zval
*this_ptr
, php_pqres_object_t
*obj
, php_pqres_fetch_t fetch_type
, zval
***row TSRMLS_DC
)
2962 php_pqres_fetch_t orig_fetch
;
2965 obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
2968 if (!obj
->intern
->iter
) {
2969 obj
->intern
->iter
= (php_pqres_iterator_t
*) php_pqres_iterator_init(Z_OBJCE_P(getThis()), getThis(), 0 TSRMLS_CC
);
2970 obj
->intern
->iter
->zi
.funcs
->rewind((zend_object_iterator
*) obj
->intern
->iter TSRMLS_CC
);
2972 orig_fetch
= obj
->intern
->iter
->fetch_type
;
2973 obj
->intern
->iter
->fetch_type
= fetch_type
;
2974 if (SUCCESS
== (rv
= obj
->intern
->iter
->zi
.funcs
->valid((zend_object_iterator
*) obj
->intern
->iter TSRMLS_CC
))) {
2975 obj
->intern
->iter
->zi
.funcs
->get_current_data((zend_object_iterator
*) obj
->intern
->iter
, row TSRMLS_CC
);
2976 obj
->intern
->iter
->zi
.funcs
->move_forward((zend_object_iterator
*) obj
->intern
->iter TSRMLS_CC
);
2978 obj
->intern
->iter
->fetch_type
= orig_fetch
;
2983 typedef struct php_pqres_col
{
2988 static STATUS
column_nn(php_pqres_object_t
*obj
, zval
*zcol
, php_pqres_col_t
*col TSRMLS_DC
)
2993 switch (Z_TYPE_P(zcol
)) {
2995 convert_to_string(zcol
);
2999 if (!is_numeric_string(Z_STRVAL_P(zcol
), Z_STRLEN_P(zcol
), &index
, NULL
, 0)) {
3000 name
= Z_STRVAL_P(zcol
);
3005 index
= Z_LVAL_P(zcol
);
3011 col
->num
= PQfnumber(obj
->intern
->res
, name
);
3013 col
->name
= PQfname(obj
->intern
->res
, index
);
3018 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Failed to find column at index %ld", index
);
3021 if (col
->num
== -1) {
3022 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Failed to find column with name '%s'", name
);
3028 static int compare_index(const void *lptr
, const void *rptr TSRMLS_DC
)
3030 const Bucket
*l
= *(const Bucket
**) lptr
;
3031 const Bucket
*r
= *(const Bucket
**) rptr
;
3042 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_bind
, 0, 0, 2)
3043 ZEND_ARG_INFO(0, col
)
3044 ZEND_ARG_INFO(1, ref
)
3045 ZEND_END_ARG_INFO();
3046 static PHP_METHOD(pqres
, bind
) {
3049 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "z/z", &zcol
, &zref
)) {
3050 php_pqres_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
3053 php_pqres_col_t col
;
3055 if (SUCCESS
== column_nn(obj
, zcol
, &col TSRMLS_CC
)) {
3057 if (SUCCESS
== zend_hash_index_update(&obj
->intern
->bound
, col
.num
, (void *) &zref
, sizeof(zval
*), NULL
)) {
3058 zend_hash_sort(&obj
->intern
->bound
, zend_qsort
, compare_index
, 0 TSRMLS_CC
);
3061 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Failed to bind column %s@%d", col
.name
, col
.num
);
3068 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Result not initialized");
3074 static int apply_bound(void *p TSRMLS_DC
, int argc
, va_list argv
, zend_hash_key
*key
)
3076 zval
**zvalue
, **zbound
= p
;
3077 zval
**zrow
= va_arg(argv
, zval
**);
3079 if (SUCCESS
== zend_hash_index_find(Z_ARRVAL_PP(zrow
), key
->h
, (void *) &zvalue
)) {
3081 ZVAL_COPY_VALUE(*zbound
, *zvalue
);
3083 zval_ptr_dtor(zvalue
);
3084 Z_ADDREF_P(*zbound
);
3086 return ZEND_HASH_APPLY_KEEP
;
3088 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Failed to find column ad index %lu", key
->h
);
3089 return ZEND_HASH_APPLY_STOP
;
3093 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_bound
, 0, 0, 0)
3094 ZEND_END_ARG_INFO();
3095 static PHP_METHOD(pqres
, fetchBound
) {
3096 zend_error_handling zeh
;
3098 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
3099 if (SUCCESS
== zend_parse_parameters_none()) {
3100 php_pqres_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
3105 if (SUCCESS
== php_pqres_iteration(getThis(), obj
, PHP_PQRES_FETCH_ARRAY
, &row TSRMLS_CC
)) {
3107 zend_hash_apply_with_arguments(&obj
->intern
->bound TSRMLS_CC
, apply_bound
, 1, row
);
3108 RETVAL_ZVAL(*row
, 1, 0);
3113 zend_restore_error_handling(&zeh TSRMLS_CC
);
3116 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_row
, 0, 0, 0)
3117 ZEND_ARG_INFO(0, fetch_type
)
3118 ZEND_END_ARG_INFO();
3119 static PHP_METHOD(pqres
, fetchRow
) {
3120 zend_error_handling zeh
;
3121 php_pqres_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
3122 long fetch_type
= -1;
3124 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
3125 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|l", &fetch_type
)) {
3129 if (fetch_type
== -1) {
3130 fetch_type
= obj
->intern
->iter
? obj
->intern
->iter
->fetch_type
: PHP_PQRES_FETCH_ARRAY
;
3132 php_pqres_iteration(getThis(), obj
, fetch_type
, &row TSRMLS_CC
);
3135 RETVAL_ZVAL(*row
, 1, 0);
3138 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Result not initialized");
3141 zend_restore_error_handling(&zeh TSRMLS_CC
);
3144 static zval
**column_at(zval
*row
, int col TSRMLS_DC
)
3147 HashTable
*ht
= HASH_OF(row
);
3148 int count
= zend_hash_num_elements(ht
);
3151 zend_hash_internal_pointer_reset(ht
);
3153 zend_hash_move_forward(ht
);
3155 zend_hash_get_current_data(ht
, (void *) &data
);
3157 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Column index %d exceeds column count %d", col
, count
);
3162 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_col
, 0, 0, 0)
3163 ZEND_ARG_INFO(0, col_num
)
3164 ZEND_END_ARG_INFO();
3165 static PHP_METHOD(pqres
, fetchCol
) {
3166 zend_error_handling zeh
;
3169 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
3170 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|l", &fetch_col
)) {
3171 php_pqres_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
3176 php_pqres_iteration(getThis(), obj
, obj
->intern
->iter
? obj
->intern
->iter
->fetch_type
: 0, &row TSRMLS_CC
);
3179 zval
**col
= column_at(*row
, fetch_col TSRMLS_CC
);
3182 RETVAL_ZVAL(*col
, 1, 0);
3186 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "pq\\Result not initialized");
3189 zend_restore_error_handling(&zeh TSRMLS_CC
);
3192 static int apply_to_col(void *p TSRMLS_DC
, int argc
, va_list argv
, zend_hash_key
*key
)
3195 php_pqres_object_t
*obj
= va_arg(argv
, php_pqres_object_t
*);
3196 php_pqres_col_t
*col
, **cols
= va_arg(argv
, php_pqres_col_t
**);
3197 STATUS
*rv
= va_arg(argv
, STATUS
*);
3200 if (SUCCESS
== column_nn(obj
, *c
, col TSRMLS_CC
)) {
3204 return ZEND_HASH_APPLY_STOP
;