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>
22 #include <libpq-events.h>
26 typedef int STATUS
; /* SUCCESS/FAILURE */
29 ZEND_DECLARE_MODULE_GLOBALS(pq)
32 const zend_function_entry pq_functions
[] = {
36 /* {{{ pq_module_entry
38 zend_module_entry pq_module_entry
= {
39 STANDARD_MODULE_HEADER
,
44 NULL
,/*PHP_RINIT(pq),*/
45 NULL
,/*PHP_RSHUTDOWN(pq),*/
48 STANDARD_MODULE_PROPERTIES
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_pqres_class_entry
;
79 static zend_class_entry
*php_pqstm_class_entry
;
81 static zend_object_handlers php_pqconn_object_handlers
;
82 static zend_object_handlers php_pqres_object_handlers
;
83 static zend_object_handlers php_pqstm_object_handlers
;
85 typedef struct php_pqconn_listener
{
87 zend_fcall_info_cache fcc
;
88 } php_pqconn_listener_t
;
90 typedef struct php_pqconn_object
{
93 int (*poller
)(PGconn
*);
96 } php_pqconn_object_t
;
98 typedef enum php_pqres_fetch
{
99 PHP_PQRES_FETCH_ARRAY
,
100 PHP_PQRES_FETCH_ASSOC
,
101 PHP_PQRES_FETCH_OBJECT
104 typedef struct php_pqres_iterator
{
105 zend_object_iterator zi
;
108 php_pqres_fetch_t fetch_type
;
109 } php_pqres_iterator_t
;
111 typedef struct php_pqres_object
{
114 php_pqres_iterator_t
*iter
;
115 } php_pqres_object_t
;
117 typedef struct php_pqstm_object
{
121 } php_pqstm_object_t
;
123 static zend_object_iterator_funcs php_pqres_iterator_funcs
;
125 static zend_object_iterator
*php_pqres_iterator_init(zend_class_entry
*ce
, zval
*object
, int by_ref TSRMLS_DC
)
127 php_pqres_iterator_t
*iter
;
128 zval
*prop
, *zfetch_type
;
130 iter
= ecalloc(1, sizeof(*iter
));
131 iter
->zi
.funcs
= &php_pqres_iterator_funcs
;
132 iter
->zi
.data
= object
;
135 zfetch_type
= prop
= zend_read_property(ce
, object
, ZEND_STRL("fetchType"), 0 TSRMLS_CC
);
136 if (Z_TYPE_P(zfetch_type
) != IS_LONG
) {
137 convert_to_long_ex(&zfetch_type
);
139 iter
->fetch_type
= Z_LVAL_P(zfetch_type
);
140 if (zfetch_type
!= prop
) {
141 zval_ptr_dtor(&zfetch_type
);
143 if (Z_REFCOUNT_P(prop
)) {
144 zval_ptr_dtor(&prop
);
150 return (zend_object_iterator
*) iter
;
153 static void php_pqres_iterator_dtor(zend_object_iterator
*i TSRMLS_DC
)
155 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
157 if (iter
->current_val
) {
158 zval_ptr_dtor(&iter
->current_val
);
159 iter
->current_val
= NULL
;
161 zval_ptr_dtor((zval
**) &iter
->zi
.data
);
165 static STATUS
php_pqres_iterator_valid(zend_object_iterator
*i TSRMLS_DC
)
167 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
168 php_pqres_object_t
*obj
= zend_object_store_get_object(iter
->zi
.data TSRMLS_CC
);
170 if (PQresultStatus(obj
->res
) != PGRES_TUPLES_OK
) {
173 if (PQntuples(obj
->res
) <= iter
->index
) {
180 static zval
*php_pqres_row_to_zval(PGresult
*res
, unsigned row
, php_pqres_fetch_t fetch_type TSRMLS_DC
)
186 if (PHP_PQRES_FETCH_OBJECT
== fetch_type
) {
192 for (c
= 0, cols
= PQnfields(res
); c
< cols
; ++c
) {
193 if (PQgetisnull(res
, row
, c
)) {
194 switch (fetch_type
) {
195 case PHP_PQRES_FETCH_OBJECT
:
196 add_property_null(data
, PQfname(res
, c
));
199 case PHP_PQRES_FETCH_ASSOC
:
200 add_assoc_null(data
, PQfname(res
, c
));
203 case PHP_PQRES_FETCH_ARRAY
:
204 add_index_null(data
, c
);
208 char *val
= PQgetvalue(res
, row
, c
);
209 int len
= PQgetlength(res
, row
, c
);
211 switch (fetch_type
) {
212 case PHP_PQRES_FETCH_OBJECT
:
213 add_property_stringl(data
, PQfname(res
, c
), val
, len
, 1);
216 case PHP_PQRES_FETCH_ASSOC
:
217 add_assoc_stringl(data
, PQfname(res
, c
), val
, len
, 1);
220 case PHP_PQRES_FETCH_ARRAY
:
221 add_index_stringl(data
, c
, val
, len
,1);
230 static void php_pqres_iterator_current(zend_object_iterator
*i
, zval
***data_ptr TSRMLS_DC
)
232 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
233 php_pqres_object_t
*obj
= zend_object_store_get_object(iter
->zi
.data TSRMLS_CC
);
235 if (iter
->current_val
) {
236 zval_ptr_dtor(&iter
->current_val
);
238 iter
->current_val
= php_pqres_row_to_zval(obj
->res
, iter
->index
, iter
->fetch_type TSRMLS_CC
);
239 *data_ptr
= &iter
->current_val
;
242 static int php_pqres_iterator_key(zend_object_iterator
*i
, char **key_str
, uint
*key_len
, ulong
*key_num TSRMLS_DC
)
244 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
246 *key_num
= (ulong
) iter
->index
;
248 return HASH_KEY_IS_LONG
;
251 static void php_pqres_iterator_next(zend_object_iterator
*i TSRMLS_DC
)
253 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
258 static void php_pqres_iterator_rewind(zend_object_iterator
*i TSRMLS_DC
)
260 php_pqres_iterator_t
*iter
= (php_pqres_iterator_t
*) i
;
265 static zend_object_iterator_funcs php_pqres_iterator_funcs
= {
266 php_pqres_iterator_dtor
,
267 /* check for end of iteration (FAILURE or SUCCESS if data is valid) */
268 php_pqres_iterator_valid
,
269 /* fetch the item data for the current element */
270 php_pqres_iterator_current
,
271 /* fetch the key for the current element (return HASH_KEY_IS_STRING or HASH_KEY_IS_LONG) (optional, may be NULL) */
272 php_pqres_iterator_key
,
273 /* step forwards to next element */
274 php_pqres_iterator_next
,
275 /* rewind to start of data (optional, may be NULL) */
276 php_pqres_iterator_rewind
,
277 /* invalidate current value/key (optional, may be NULL) */
281 static void php_pqconn_object_free(void *o TSRMLS_DC
)
283 php_pqconn_object_t
*obj
= o
;
289 zend_hash_destroy(&obj
->listeners
);
290 zend_object_std_dtor((zend_object
*) o TSRMLS_CC
);
294 static void php_pqres_object_free(void *o TSRMLS_DC
)
296 php_pqres_object_t
*obj
= o
;
303 php_pqres_iterator_dtor((zend_object_iterator
*) obj
->iter TSRMLS_CC
);
306 zend_object_std_dtor((zend_object
*) o TSRMLS_CC
);
310 static void php_pqstm_object_free(void *o TSRMLS_DC
)
312 php_pqstm_object_t
*obj
= o
;
319 zval_ptr_dtor(&obj
->conn
);
322 zend_object_std_dtor((zend_object
*) o TSRMLS_CC
);
326 static zend_object_value
php_pqconn_create_object_ex(zend_class_entry
*ce
, PGconn
*conn
, php_pqconn_object_t
**ptr TSRMLS_DC
)
328 zend_object_value ov
;
329 php_pqconn_object_t
*o
;
331 o
= ecalloc(1, sizeof(*o
));
332 zend_object_std_init((zend_object
*) o
, ce TSRMLS_CC
);
333 object_properties_init((zend_object
*) o
, ce
);
341 o
->async
= !PQisnonblocking(o
->conn
);
344 zend_hash_init(&o
->listeners
, 0, NULL
, (dtor_func_t
) zend_hash_destroy
, 0);
346 ov
.handle
= zend_objects_store_put((zend_object
*) o
, NULL
, php_pqconn_object_free
, NULL TSRMLS_CC
);
347 ov
.handlers
= &php_pqconn_object_handlers
;
352 static zend_object_value
php_pqres_create_object_ex(zend_class_entry
*ce
, PGresult
*res
, php_pqres_object_t
**ptr TSRMLS_DC
)
354 zend_object_value ov
;
355 php_pqres_object_t
*o
;
357 o
= ecalloc(1, sizeof(*o
));
358 zend_object_std_init((zend_object
*) o
, ce TSRMLS_CC
);
359 object_properties_init((zend_object
*) o
, ce
);
369 ov
.handle
= zend_objects_store_put((zend_object
*) o
, NULL
, php_pqres_object_free
, NULL TSRMLS_CC
);
370 ov
.handlers
= &php_pqres_object_handlers
;
375 static zend_object_value
php_pqstm_create_object_ex(zend_class_entry
*ce
, zval
*conn
, const char *name
, php_pqstm_object_t
**ptr TSRMLS_DC
)
377 zend_object_value ov
;
378 php_pqstm_object_t
*o
;
380 o
= ecalloc(1, sizeof(*o
));
381 zend_object_std_init((zend_object
*) o
, ce TSRMLS_CC
);
382 object_properties_init((zend_object
*) o
, ce
);
394 o
->name
= estrdup(name
);
397 ov
.handle
= zend_objects_store_put((zend_object
*) o
, NULL
, php_pqstm_object_free
, NULL TSRMLS_CC
);
398 ov
.handlers
= &php_pqstm_object_handlers
;
403 static zend_object_value
php_pqconn_create_object(zend_class_entry
*class_type TSRMLS_DC
)
405 return php_pqconn_create_object_ex(class_type
, NULL
, NULL TSRMLS_CC
);
408 static zend_object_value
php_pqres_create_object(zend_class_entry
*class_type TSRMLS_DC
)
410 return php_pqres_create_object_ex(class_type
, NULL
, NULL TSRMLS_CC
);
413 static zend_object_value
php_pqstm_create_object(zend_class_entry
*class_type TSRMLS_DC
)
415 return php_pqstm_create_object_ex(class_type
, NULL
, NULL
, NULL TSRMLS_CC
);
418 static HashTable php_pqconn_object_prophandlers
;
419 static HashTable php_pqres_object_prophandlers
;
420 static HashTable php_pqstm_object_prophandlers
;
422 typedef void (*php_pq_object_prophandler_func_t
)(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
);
424 typedef struct php_pq_object_prophandler
{
425 php_pq_object_prophandler_func_t read
;
426 php_pq_object_prophandler_func_t write
;
427 } php_pq_object_prophandler_t
;
429 static void php_pqconn_object_read_status(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
431 php_pqconn_object_t
*obj
= o
;
433 RETVAL_LONG(PQstatus(obj
->conn
));
436 static void php_pqconn_object_read_transaction_status(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
438 php_pqconn_object_t
*obj
= o
;
440 RETVAL_LONG(PQtransactionStatus(obj
->conn
));
443 static void php_pqconn_object_read_error_message(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
445 php_pqconn_object_t
*obj
= o
;
446 char *error
= PQerrorMessage(obj
->conn
);
449 RETVAL_STRING(error
, 1);
455 static int apply_notify_listener(void *p
, void *arg TSRMLS_DC
)
457 php_pqconn_listener_t
*listener
= p
;
459 zval
*zpid
, *zchannel
, *zmessage
;
462 ZVAL_LONG(zpid
, nfy
->be_pid
);
463 MAKE_STD_ZVAL(zchannel
);
464 ZVAL_STRING(zchannel
, nfy
->relname
, 1);
465 MAKE_STD_ZVAL(zmessage
);
466 ZVAL_STRING(zmessage
, nfy
->extra
, 1);
468 zend_fcall_info_argn(&listener
->fci TSRMLS_CC
, 3, &zchannel
, &zmessage
, &zpid
);
469 zend_fcall_info_call(&listener
->fci
, &listener
->fcc
, NULL
, NULL TSRMLS_CC
);
471 zval_ptr_dtor(&zchannel
);
472 zval_ptr_dtor(&zmessage
);
473 zval_ptr_dtor(&zpid
);
475 return ZEND_HASH_APPLY_KEEP
;
478 static int apply_notify_listeners(void *p
, void *arg TSRMLS_DC
)
480 HashTable
*listeners
= p
;
482 zend_hash_apply_with_argument(listeners
, apply_notify_listener
, arg TSRMLS_CC
);
484 return ZEND_HASH_APPLY_KEEP
;
487 static void php_pqconn_notify_listeners(zval
*this_ptr
, php_pqconn_object_t
*obj TSRMLS_DC
)
492 obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
495 while ((nfy
= PQnotifies(obj
->conn
))) {
496 zend_hash_apply_with_argument(&obj
->listeners
, apply_notify_listeners
, nfy TSRMLS_CC
);
501 /* FIXME: extend to types->nspname->typname */
502 #define PHP_PQ_TYPES_QUERY \
503 "select t.oid, t.* " \
504 "from pg_type t join pg_namespace n on t.typnamespace=n.oid " \
505 "where typisdefined " \
507 "and nspname in ('public', 'pg_catalog')"
508 static void php_pqconn_object_read_types(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
510 php_pqconn_object_t
*obj
= o
;
511 PGresult
*res
= PQexec(obj
->conn
, PHP_PQ_TYPES_QUERY
);
513 php_pqconn_notify_listeners(object
, obj TSRMLS_CC
);
515 /* FIXME: cache that */
517 if (PGRES_TUPLES_OK
== PQresultStatus(res
)) {
519 zval
*byoid
, *byname
;
521 MAKE_STD_ZVAL(byoid
);
522 MAKE_STD_ZVAL(byname
);
525 object_init(return_value
);
526 for (r
= 0, rows
= PQntuples(res
); r
< rows
; ++r
) {
527 zval
*row
= php_pqres_row_to_zval(res
, r
, PHP_PQRES_FETCH_OBJECT TSRMLS_CC
);
529 add_property_zval(byoid
, PQgetvalue(res
, r
, 0), row
);
530 add_property_zval(byname
, PQgetvalue(res
, r
, 1), row
);
534 add_property_zval(return_value
, "byOid", byoid
);
535 add_property_zval(return_value
, "byName", byname
);
536 zval_ptr_dtor(&byoid
);
537 zval_ptr_dtor(&byname
);
539 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not fetch types: %s", PQresultErrorMessage(res
));
543 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not fetch types: %s", PQerrorMessage(obj
->conn
));
547 static void php_pqres_object_read_status(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
549 php_pqres_object_t
*obj
= o
;
551 RETVAL_LONG(PQresultStatus(obj
->res
));
554 static void php_pqres_object_read_error_message(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
556 php_pqres_object_t
*obj
= o
;
557 char *error
= PQresultErrorMessage(obj
->res
);
560 RETVAL_STRING(error
, 1);
566 static void php_pqres_object_read_num_rows(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
568 php_pqres_object_t
*obj
= o
;
570 RETVAL_LONG(PQntuples(obj
->res
));
573 static void php_pqres_object_read_num_cols(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
575 php_pqres_object_t
*obj
= o
;
577 RETVAL_LONG(PQnfields(obj
->res
));
580 static void php_pqres_object_read_affected_rows(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
582 php_pqres_object_t
*obj
= o
;
584 RETVAL_LONG(atoi(PQcmdTuples(obj
->res
)));
587 static void php_pqres_object_read_fetch_type(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
589 php_pqres_object_t
*obj
= o
;
592 RETVAL_LONG(obj
->iter
->fetch_type
);
594 RETVAL_LONG(PHP_PQRES_FETCH_ARRAY
);
598 static void php_pqres_object_write_fetch_type(zval
*object
, void *o
, zval
*value TSRMLS_DC
)
600 php_pqres_object_t
*obj
= o
;
601 zval
*zfetch_type
= value
;
603 if (Z_TYPE_P(zfetch_type
) != IS_LONG
) {
604 convert_to_long_ex(&zfetch_type
);
607 obj
->iter
->fetch_type
= Z_LVAL_P(zfetch_type
);
609 if (zfetch_type
!= value
) {
610 zval_ptr_dtor(&zfetch_type
);
614 static void php_pqstm_object_read_name(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
616 php_pqstm_object_t
*obj
= o
;
618 RETVAL_STRING(obj
->name
, 1);
621 static void php_pqstm_object_read_connection(zval
*object
, void *o
, zval
*return_value TSRMLS_DC
)
623 php_pqstm_object_t
*obj
= o
;
625 RETVAL_ZVAL(obj
->conn
, 1, 0);
628 static zval
*php_pqconn_object_read_prop(zval
*object
, zval
*member
, int type
, const zend_literal
*key TSRMLS_DC
)
630 php_pqconn_object_t
*obj
= zend_object_store_get_object(object TSRMLS_CC
);
631 php_pq_object_prophandler_t
*handler
;
635 zend_error(E_WARNING
, "Connection not initialized");
636 } else if ((SUCCESS
== zend_hash_find(&php_pqconn_object_prophandlers
, Z_STRVAL_P(member
), Z_STRLEN_P(member
)+1, (void *) &handler
)) && handler
->read
) {
637 if (type
== BP_VAR_R
) {
638 ALLOC_ZVAL(return_value
);
639 Z_SET_REFCOUNT_P(return_value
, 0);
640 Z_UNSET_ISREF_P(return_value
);
642 handler
->read(object
, obj
, return_value TSRMLS_CC
);
644 zend_error(E_ERROR
, "Cannot access pq\\Connection properties by reference or array key/index");
648 return_value
= zend_get_std_object_handlers()->read_property(object
, member
, type
, key TSRMLS_CC
);
654 static void php_pqconn_object_write_prop(zval
*object
, zval
*member
, zval
*value
, const zend_literal
*key TSRMLS_DC
)
656 php_pqconn_object_t
*obj
= zend_object_store_get_object(object TSRMLS_CC
);
657 php_pq_object_prophandler_t
*handler
;
659 if (SUCCESS
== zend_hash_find(&php_pqconn_object_prophandlers
, Z_STRVAL_P(member
), Z_STRLEN_P(member
)+1, (void *) &handler
)) {
660 if (handler
->write
) {
661 handler
->write(object
, obj
, value TSRMLS_CC
);
664 zend_get_std_object_handlers()->write_property(object
, member
, value
, key TSRMLS_CC
);
668 static zval
*php_pqres_object_read_prop(zval
*object
, zval
*member
, int type
, const zend_literal
*key TSRMLS_DC
)
670 php_pqres_object_t
*obj
= zend_object_store_get_object(object TSRMLS_CC
);
671 php_pq_object_prophandler_t
*handler
;
675 zend_error(E_WARNING
, "Result not initialized");
676 } else if (SUCCESS
== zend_hash_find(&php_pqres_object_prophandlers
, Z_STRVAL_P(member
), Z_STRLEN_P(member
)+1, (void *) &handler
)) {
677 if (type
== BP_VAR_R
) {
678 ALLOC_ZVAL(return_value
);
679 Z_SET_REFCOUNT_P(return_value
, 0);
680 Z_UNSET_ISREF_P(return_value
);
682 handler
->read(object
, obj
, return_value TSRMLS_CC
);
684 zend_error(E_ERROR
, "Cannot access pq\\Result properties by reference or array key/index");
688 return_value
= zend_get_std_object_handlers()->read_property(object
, member
, type
, key TSRMLS_CC
);
694 static void php_pqres_object_write_prop(zval
*object
, zval
*member
, zval
*value
, const zend_literal
*key TSRMLS_DC
)
696 php_pqres_object_t
*obj
= zend_object_store_get_object(object TSRMLS_CC
);
697 php_pq_object_prophandler_t
*handler
;
700 zend_error(E_WARNING
, "Result not initialized");
701 } else if (SUCCESS
== zend_hash_find(&php_pqres_object_prophandlers
, Z_STRVAL_P(member
), Z_STRLEN_P(member
)+1, (void *) &handler
)) {
702 if (handler
->write
) {
703 /* ensure obj->iter is initialized, for e.g. write_fetch_type */
705 obj
->iter
= (php_pqres_iterator_t
*) php_pqres_iterator_init(Z_OBJCE_P(object
), object
, 0 TSRMLS_CC
);
706 obj
->iter
->zi
.funcs
->rewind((zend_object_iterator
*) obj
->iter TSRMLS_CC
);
708 handler
->write(object
, obj
, value TSRMLS_CC
);
711 zend_get_std_object_handlers()->write_property(object
, member
, value
, key TSRMLS_CC
);
715 static zval
*php_pqstm_object_read_prop(zval
*object
, zval
*member
, int type
, const zend_literal
*key TSRMLS_DC
)
717 php_pqstm_object_t
*obj
= zend_object_store_get_object(object TSRMLS_CC
);
718 php_pq_object_prophandler_t
*handler
;
722 zend_error(E_WARNING
, "Statement not initialized");
723 } else if (SUCCESS
== zend_hash_find(&php_pqstm_object_prophandlers
, Z_STRVAL_P(member
), Z_STRLEN_P(member
)+1, (void *) &handler
)) {
724 if (type
== BP_VAR_R
) {
725 ALLOC_ZVAL(return_value
);
726 Z_SET_REFCOUNT_P(return_value
, 0);
727 Z_UNSET_ISREF_P(return_value
);
729 handler
->read(object
, obj
, return_value TSRMLS_CC
);
731 zend_error(E_ERROR
, "Cannot access pq\\Statement properties by reference or array key/index");
735 return_value
= zend_get_std_object_handlers()->read_property(object
, member
, type
, key TSRMLS_CC
);
741 static void php_pqstm_object_write_prop(zval
*object
, zval
*member
, zval
*value
, const zend_literal
*key TSRMLS_DC
)
743 php_pqstm_object_t
*obj
= zend_object_store_get_object(object TSRMLS_CC
);
744 php_pq_object_prophandler_t
*handler
;
747 zend_error(E_WARNING
, "Result not initialized");
748 } else if (SUCCESS
== zend_hash_find(&php_pqstm_object_prophandlers
, Z_STRVAL_P(member
), Z_STRLEN_P(member
)+1, (void *) &handler
)) {
749 if (handler
->write
) {
750 handler
->write(object
, obj
, value TSRMLS_CC
);
753 zend_get_std_object_handlers()->write_property(object
, member
, value
, key TSRMLS_CC
);
757 static STATUS
php_pqconn_update_socket(zval
*this_ptr
, php_pqconn_object_t
*obj TSRMLS_DC
)
759 zval
*zsocket
, zmember
;
765 obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
768 INIT_PZVAL(&zmember
);
769 ZVAL_STRINGL(&zmember
, "socket", sizeof("socket")-1, 0);
770 MAKE_STD_ZVAL(zsocket
);
772 if ((CONNECTION_BAD
!= PQstatus(obj
->conn
))
773 && (-1 < (socket
= PQsocket(obj
->conn
)))
774 && (stream
= php_stream_fopen_from_fd(socket
, "r+b", NULL
))) {
775 php_stream_to_zval(stream
, zsocket
);
781 zend_get_std_object_handlers()->write_property(getThis(), &zmember
, zsocket
, NULL TSRMLS_CC
);
782 zval_ptr_dtor(&zsocket
);
787 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_construct
, 0, 0, 1)
788 ZEND_ARG_INFO(0, dsn
)
789 ZEND_ARG_INFO(0, async
)
791 static PHP_METHOD(pqconn
, __construct
) {
792 zend_error_handling zeh
;
797 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
798 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s|b", &dsn_str
, &dsn_len
, &async
)) {
799 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
804 if ((obj
->async
= async
)) {
805 obj
->conn
= PQconnectStart(dsn_str
);
806 obj
->poller
= (int (*)(PGconn
*)) PQconnectPoll
;
808 obj
->conn
= PQconnectdb(dsn_str
);
811 if (SUCCESS
!= php_pqconn_update_socket(getThis(), obj TSRMLS_CC
)) {
812 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Connection failed: %s", PQerrorMessage(obj
->conn
));
815 zend_restore_error_handling(&zeh TSRMLS_CC
);
818 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_reset
, 0, 0, 0)
820 static PHP_METHOD(pqconn
, reset
) {
821 if (SUCCESS
== zend_parse_parameters_none()) {
822 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
826 if (PQresetStart(obj
->conn
)) {
827 obj
->poller
= (int (*)(PGconn
*)) PQresetPoll
;
833 if (CONNECTION_OK
== PQstatus(obj
->conn
)) {
836 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Connection reset failed: %s", PQerrorMessage(obj
->conn
));
840 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Connection not initialized");
846 static void listener_dtor(void *l
) {
847 php_pqconn_listener_t
*listener
= l
;
849 zend_fcall_info_args_clear(&listener
->fci
, 1);
851 zval_ptr_dtor(&listener
->fci
.function_name
);
852 if (listener
->fci
.object_ptr
) {
853 zval_ptr_dtor(&listener
->fci
.object_ptr
);
857 static void php_pqconn_add_listener(php_pqconn_object_t
*obj
, const char *channel_str
, size_t channel_len
, php_pqconn_listener_t
*listener TSRMLS_DC
)
859 HashTable ht
, *existing_listeners
;
861 Z_ADDREF_P(listener
->fci
.function_name
);
862 if (listener
->fci
.object_ptr
) {
863 Z_ADDREF_P(listener
->fci
.object_ptr
);
865 if (SUCCESS
== zend_hash_find(&obj
->listeners
, channel_str
, channel_len
+ 1, (void *) &existing_listeners
)) {
866 zend_hash_next_index_insert(existing_listeners
, (void *) listener
, sizeof(*listener
), NULL
);
868 zend_hash_init(&ht
, 1, NULL
, (dtor_func_t
) listener_dtor
, 0);
869 zend_hash_next_index_insert(&ht
, (void *) listener
, sizeof(*listener
), NULL
);
870 zend_hash_add(&obj
->listeners
, channel_str
, channel_len
+ 1, (void *) &ht
, sizeof(HashTable
), NULL
);
874 static STATUS
php_pqres_success(PGresult
*res TSRMLS_DC
)
876 switch (PQresultStatus(res
)) {
877 case PGRES_BAD_RESPONSE
:
878 case PGRES_NONFATAL_ERROR
:
879 case PGRES_FATAL_ERROR
:
880 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "%s", PQresultErrorMessage(res
));
887 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_listen
, 0, 0, 0)
888 ZEND_ARG_INFO(0, channel
)
889 ZEND_ARG_INFO(0, callable
)
891 static PHP_METHOD(pqconn
, listen
) {
892 char *channel_str
= NULL
;
894 php_pqconn_listener_t listener
;
896 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "sf", &channel_str
, &channel_len
, &listener
.fci
, &listener
.fcc
)) {
897 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
899 obj
->poller
= PQconsumeInput
;
905 slprintf(cmd
, sizeof(cmd
), "LISTEN %s", channel_str
);
906 res
= PQexec(obj
->conn
, cmd
);
909 if (SUCCESS
== php_pqres_success(res TSRMLS_CC
)) {
910 php_pqconn_add_listener(obj
, channel_str
, channel_len
, &listener TSRMLS_CC
);
917 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not install listener: %s", PQerrorMessage(obj
->conn
));
921 php_pqconn_notify_listeners(getThis(), obj TSRMLS_CC
);
924 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Connection not initialized");
931 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_notify
, 0, 0, 2)
932 ZEND_ARG_INFO(0, channel
)
933 ZEND_ARG_INFO(0, message
)
935 static PHP_METHOD(pqconn
, notify
) {
936 char *channel_str
, *message_str
;
937 int channel_len
, message_len
;
939 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "ss", &channel_str
, &channel_len
, &message_str
, &message_len
)) {
940 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
944 char *params
[2] = {channel_str
, message_str
};
946 res
= PQexecParams(obj
->conn
, "select pg_notify($1, $2)", 2, NULL
, (const char *const*) params
, NULL
, NULL
, 0);
949 if (SUCCESS
== php_pqres_success(res TSRMLS_CC
)) {
956 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not notify listeners: %s", PQerrorMessage(obj
->conn
));
960 php_pqconn_notify_listeners(getThis(), obj TSRMLS_CC
);
963 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Connection not initialized");
969 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_poll
, 0, 0, 0)
971 static PHP_METHOD(pqconn
, poll
) {
972 if (SUCCESS
== zend_parse_parameters_none()) {
973 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
977 if (obj
->poller
== PQconsumeInput
) {
978 RETVAL_LONG(obj
->poller(obj
->conn
) * PGRES_POLLING_OK
);
979 php_pqconn_notify_listeners(getThis(), obj TSRMLS_CC
);
982 RETURN_LONG(obj
->poller(obj
->conn
));
985 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "No asynchronous operation active");
988 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Connection not initialized");
994 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec
, 0, 0, 1)
995 ZEND_ARG_INFO(0, query
)
997 static PHP_METHOD(pqconn
, exec
) {
998 zend_error_handling zeh
;
1002 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
1003 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "s", &query_str
, &query_len
)) {
1004 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1007 PGresult
*res
= PQexec(obj
->conn
, query_str
);
1009 php_pqconn_notify_listeners(getThis(), obj TSRMLS_CC
);
1012 if (SUCCESS
== php_pqres_success(res TSRMLS_CC
)) {
1013 return_value
->type
= IS_OBJECT
;
1014 return_value
->value
.obj
= php_pqres_create_object_ex(php_pqres_class_entry
, res
, NULL TSRMLS_CC
);
1017 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not execute query: %s", PQerrorMessage(obj
->conn
));
1020 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Connection not initialized");
1023 zend_restore_error_handling(&zeh TSRMLS_CC
);
1026 static int apply_to_oid(void *p
, void *arg TSRMLS_DC
)
1031 if (Z_TYPE_PP(ztype
) != IS_LONG
) {
1032 convert_to_long_ex(ztype
);
1035 **types
= Z_LVAL_PP(ztype
);
1038 if (*ztype
!= *(zval
**)p
) {
1039 zval_ptr_dtor(ztype
);
1041 return ZEND_HASH_APPLY_KEEP
;
1044 static int apply_to_param(void *p TSRMLS_DC
, int argc
, va_list argv
, zend_hash_key
*key
)
1050 params
= (char ***) va_arg(argv
, char ***);
1051 zdtor
= (HashTable
*) va_arg(argv
, HashTable
*);
1053 if (Z_TYPE_PP(zparam
) == IS_NULL
) {
1057 if (Z_TYPE_PP(zparam
) != IS_STRING
) {
1058 convert_to_string_ex(zparam
);
1061 **params
= Z_STRVAL_PP(zparam
);
1064 if (*zparam
!= *(zval
**)p
) {
1065 zend_hash_next_index_insert(zdtor
, zparam
, sizeof(zval
*), NULL
);
1068 return ZEND_HASH_APPLY_KEEP
;
1071 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_params
, 0, 0, 2)
1072 ZEND_ARG_INFO(0, query
)
1073 ZEND_ARG_ARRAY_INFO(0, params
, 0)
1074 ZEND_ARG_ARRAY_INFO(0, types
, 1)
1075 ZEND_END_ARG_INFO();
1076 static PHP_METHOD(pqconn
, execParams
) {
1077 zend_error_handling zeh
;
1081 zval
*ztypes
= NULL
;
1083 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
1084 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "sa/|a/!", &query_str
, &query_len
, &zparams
, &ztypes
)) {
1085 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1091 char **params
= NULL
;
1094 ZEND_INIT_SYMTABLE(&zdtor
);
1096 if (ztypes
&& zend_hash_num_elements(Z_ARRVAL_P(ztypes
))) {
1099 tmp
= types
= ecalloc(zend_hash_num_elements(Z_ARRVAL_P(ztypes
)), sizeof(Oid
));
1100 zend_hash_apply_with_argument(Z_ARRVAL_P(ztypes
), apply_to_oid
, &tmp TSRMLS_CC
);
1102 if ((count
= zend_hash_num_elements(Z_ARRVAL_P(zparams
)))) {
1105 tmp
= params
= ecalloc(zend_hash_num_elements(Z_ARRVAL_P(zparams
)), sizeof(char *));
1106 zend_hash_apply_with_arguments(Z_ARRVAL_P(zparams
) TSRMLS_CC
, apply_to_param
, 2, &tmp
, &zdtor
);
1109 res
= PQexecParams(obj
->conn
, query_str
, count
, types
, (const char *const*) params
, NULL
, NULL
, 0);
1111 zend_hash_destroy(&zdtor
);
1119 php_pqconn_notify_listeners(getThis(), obj TSRMLS_CC
);
1122 if (SUCCESS
== php_pqres_success(res TSRMLS_CC
)) {
1123 return_value
->type
= IS_OBJECT
;
1124 return_value
->value
.obj
= php_pqres_create_object_ex(php_pqres_class_entry
, res
, NULL TSRMLS_CC
);
1127 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not execute query: %s", PQerrorMessage(obj
->conn
));
1130 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Connection not initialized");
1133 zend_restore_error_handling(&zeh TSRMLS_CC
);
1136 static STATUS
php_pqconn_prepare(PGconn
*conn
, const char *name
, const char *query
, HashTable
*typest TSRMLS_DC
)
1142 if (typest
&& (count
= zend_hash_num_elements(typest
))) {
1145 tmp
= types
= ecalloc(count
, sizeof(Oid
));
1146 zend_hash_apply_with_argument(typest
, apply_to_oid
, &tmp TSRMLS_CC
);
1149 res
= PQprepare(conn
, name
, query
, count
, types
);
1156 if (PGRES_COMMAND_OK
== PQresultStatus(res
)) {
1159 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not prepare statement: %s", PQresultErrorMessage(res
));
1163 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not prepare statement: %s", PQerrorMessage(conn
));
1168 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_prepare
, 0, 0, 2)
1169 ZEND_ARG_INFO(0, "name")
1170 ZEND_ARG_INFO(0, "query")
1171 ZEND_ARG_ARRAY_INFO(0, "types", 1)
1172 ZEND_END_ARG_INFO();
1173 static PHP_METHOD(pqconn
, prepare
) {
1174 zend_error_handling zeh
;
1175 zval
*ztypes
= NULL
;
1176 char *name_str
, *query_str
;
1177 int name_len
, *query_len
;
1179 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
1180 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "ss|a/!", &name_str
, &name_len
, &query_str
, &query_len
, &ztypes
)) {
1181 php_pqconn_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1184 if (SUCCESS
== php_pqconn_prepare(obj
->conn
, name_str
, query_str
, ztypes
? Z_ARRVAL_P(ztypes
) : NULL TSRMLS_CC
)) {
1185 return_value
->type
= IS_OBJECT
;
1186 return_value
->value
.obj
= php_pqstm_create_object_ex(php_pqstm_class_entry
, getThis(), name_str
, NULL TSRMLS_CC
);
1188 php_pqconn_notify_listeners(getThis(), obj TSRMLS_CC
);
1190 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Connection not initialized");
1195 static zend_function_entry php_pqconn_methods
[] = {
1196 PHP_ME(pqconn
, __construct
, ai_pqconn_construct
, ZEND_ACC_PUBLIC
|ZEND_ACC_CTOR
)
1197 PHP_ME(pqconn
, reset
, ai_pqconn_reset
, ZEND_ACC_PUBLIC
)
1198 PHP_ME(pqconn
, poll
, ai_pqconn_poll
, ZEND_ACC_PUBLIC
)
1199 PHP_ME(pqconn
, exec
, ai_pqconn_exec
, ZEND_ACC_PUBLIC
)
1200 PHP_ME(pqconn
, execParams
, ai_pqconn_exec_params
, ZEND_ACC_PUBLIC
)
1201 PHP_ME(pqconn
, prepare
, ai_pqconn_prepare
, ZEND_ACC_PUBLIC
)
1202 PHP_ME(pqconn
, listen
, ai_pqconn_listen
, ZEND_ACC_PUBLIC
)
1203 PHP_ME(pqconn
, notify
, ai_pqconn_notify
, ZEND_ACC_PUBLIC
)
1207 static zval
**php_pqres_iteration(zval
*this_ptr
, php_pqres_object_t
*obj
, php_pqres_fetch_t fetch_type TSRMLS_DC
)
1210 php_pqres_fetch_t orig_fetch
;
1213 obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1217 obj
->iter
= (php_pqres_iterator_t
*) php_pqres_iterator_init(Z_OBJCE_P(getThis()), getThis(), 0 TSRMLS_CC
);
1218 obj
->iter
->zi
.funcs
->rewind((zend_object_iterator
*) obj
->iter TSRMLS_CC
);
1220 orig_fetch
= obj
->iter
->fetch_type
;
1221 obj
->iter
->fetch_type
= fetch_type
;
1222 if (SUCCESS
== obj
->iter
->zi
.funcs
->valid((zend_object_iterator
*) obj
->iter TSRMLS_CC
)) {
1223 obj
->iter
->zi
.funcs
->get_current_data((zend_object_iterator
*) obj
->iter
, &row TSRMLS_CC
);
1224 obj
->iter
->zi
.funcs
->move_forward((zend_object_iterator
*) obj
->iter TSRMLS_CC
);
1226 obj
->iter
->fetch_type
= orig_fetch
;
1228 return row
? row
: NULL
;
1231 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_row
, 0, 0, 0)
1232 ZEND_ARG_INFO(0, fetch_type
)
1233 ZEND_END_ARG_INFO();
1234 static PHP_METHOD(pqres
, fetchRow
) {
1235 zend_error_handling zeh
;
1236 php_pqres_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1237 long fetch_type
= obj
->iter
? obj
->iter
->fetch_type
: PHP_PQRES_FETCH_ARRAY
;
1239 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
1240 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|l", &fetch_type
)) {
1241 zval
**row
= php_pqres_iteration(getThis(), obj
, fetch_type TSRMLS_CC
);
1244 RETVAL_ZVAL(*row
, 1, 0);
1249 zend_restore_error_handling(&zeh TSRMLS_CC
);
1252 static zval
**column_at(zval
*row
, int col TSRMLS_DC
)
1255 HashTable
*ht
= HASH_OF(row
);
1256 int count
= zend_hash_num_elements(ht
);
1259 zend_hash_internal_pointer_reset(ht
);
1261 zend_hash_move_forward(ht
);
1263 zend_hash_get_current_data(ht
, (void *) &data
);
1265 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Column index %d does excess column count %d", col
, count
);
1270 ZEND_BEGIN_ARG_INFO_EX(ai_pqres_fetch_col
, 0, 0, 0)
1271 ZEND_ARG_INFO(0, col_num
)
1272 ZEND_END_ARG_INFO();
1273 static PHP_METHOD(pqres
, fetchCol
) {
1274 zend_error_handling zeh
;
1277 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
1278 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|l", &fetch_col
)) {
1279 php_pqres_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1280 zval
**row
= php_pqres_iteration(getThis(), obj
, obj
->iter
? obj
->iter
->fetch_type
: 0 TSRMLS_CC
);
1283 zval
**col
= column_at(*row
, fetch_col TSRMLS_CC
);
1286 RETVAL_ZVAL(*col
, 1, 0);
1294 zend_restore_error_handling(&zeh TSRMLS_CC
);
1298 static zend_function_entry php_pqres_methods
[] = {
1299 PHP_ME(pqres
, fetchRow
, ai_pqres_fetch_row
, ZEND_ACC_PUBLIC
)
1300 PHP_ME(pqres
, fetchCol
, ai_pqres_fetch_col
, ZEND_ACC_PUBLIC
)
1304 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_construct
, 0, 0, 3)
1305 ZEND_ARG_OBJ_INFO(0, "Connection", "pq\\Connection", 0)
1306 ZEND_ARG_INFO(0, "name")
1307 ZEND_ARG_INFO(0, "query")
1308 ZEND_ARG_ARRAY_INFO(0, "types", 1)
1309 ZEND_END_ARG_INFO();
1310 static PHP_METHOD(pqstm
, __construct
) {
1311 zend_error_handling zeh
;
1312 zval
*zconn
, *ztypes
= NULL
;
1313 char *name_str
, *query_str
;
1314 int name_len
, *query_len
;
1316 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
1317 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "Oss|a/!", &zconn
, php_pqconn_class_entry
, &name_str
, &name_len
, &query_str
, &query_len
, &ztypes
)) {
1318 php_pqstm_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1319 php_pqconn_object_t
*conn_obj
= zend_object_store_get_object(zconn TSRMLS_CC
);
1321 if (conn_obj
->conn
) {
1322 if (SUCCESS
== php_pqconn_prepare(conn_obj
->conn
, name_str
, query_str
, ztypes
? Z_ARRVAL_P(ztypes
) : NULL TSRMLS_CC
)) {
1325 obj
->name
= estrdup(name_str
);
1327 php_pqconn_notify_listeners(obj
->conn
, conn_obj TSRMLS_CC
);
1329 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Connection not initialized");
1334 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_exec
, 0, 0, 0)
1335 ZEND_ARG_ARRAY_INFO(0, "params", 1)
1336 ZEND_END_ARG_INFO();
1337 static PHP_METHOD(pqstm
, exec
) {
1338 zend_error_handling zeh
;
1339 zval
*zparams
= NULL
;
1341 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
1342 if (SUCCESS
== zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC
, "|a/!", &zparams
)) {
1343 php_pqstm_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1345 if (obj
->conn
&& obj
->name
) {
1346 php_pqconn_object_t
*conn_obj
= zend_object_store_get_object(obj
->conn TSRMLS_CC
);
1348 if (conn_obj
->conn
) {
1350 char **params
= NULL
;
1354 ZEND_INIT_SYMTABLE(&zdtor
);
1356 if (zparams
&& (count
= zend_hash_num_elements(Z_ARRVAL_P(zparams
)))) {
1359 tmp
= params
= ecalloc(count
, sizeof(char *));
1360 zend_hash_apply_with_arguments(Z_ARRVAL_P(zparams
) TSRMLS_CC
, apply_to_param
, 2, &tmp
, &zdtor
);
1363 res
= PQexecPrepared(conn_obj
->conn
, obj
->name
, count
, (const char *const*) params
, NULL
, NULL
, 0);
1368 zend_hash_destroy(&zdtor
);
1370 php_pqconn_notify_listeners(obj
->conn
, conn_obj TSRMLS_CC
);
1373 if (SUCCESS
== php_pqres_success(res TSRMLS_CC
)) {
1374 return_value
->type
= IS_OBJECT
;
1375 return_value
->value
.obj
= php_pqres_create_object_ex(php_pqres_class_entry
, res
, NULL TSRMLS_CC
);
1378 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not execute statement: %s", PQerrorMessage(conn_obj
->conn
));
1381 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Connection not initialized");
1384 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Statement not initialized");
1387 zend_restore_error_handling(&zeh TSRMLS_CC
);
1390 ZEND_BEGIN_ARG_INFO_EX(ai_pqstm_desc
, 0, 0, 0)
1391 ZEND_END_ARG_INFO();
1392 static PHP_METHOD(pqstm
, desc
) {
1393 zend_error_handling zeh
;
1395 zend_replace_error_handling(EH_THROW
, NULL
, &zeh TSRMLS_CC
);
1396 if (SUCCESS
== zend_parse_parameters_none()) {
1397 php_pqstm_object_t
*obj
= zend_object_store_get_object(getThis() TSRMLS_CC
);
1399 if (obj
->conn
&& obj
->name
) {
1400 php_pqconn_object_t
*conn_obj
= zend_object_store_get_object(obj
->conn TSRMLS_CC
);
1402 if (conn_obj
->conn
) {
1403 PGresult
*res
= PQdescribePrepared(conn_obj
->conn
, obj
->name
);
1405 php_pqconn_notify_listeners(obj
->conn
, conn_obj TSRMLS_CC
);
1408 if (SUCCESS
== php_pqres_success(res TSRMLS_CC
)) {
1411 array_init(return_value
);
1412 for (p
= 0, params
= PQnparams(res
); p
< params
; ++p
) {
1413 add_next_index_long(return_value
, PQparamtype(res
, p
));
1417 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Could not describe statement: %s", PQerrorMessage(conn_obj
->conn
));
1420 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Connection not initialized");
1423 php_error_docref(NULL TSRMLS_CC
, E_WARNING
, "Statement not initialized");
1426 zend_restore_error_handling(&zeh TSRMLS_CC
);
1429 static zend_function_entry php_pqstm_methods
[] = {
1430 PHP_ME(pqstm
, __construct
, ai_pqstm_construct
, ZEND_ACC_PUBLIC
|ZEND_ACC_CTOR
)
1431 PHP_ME(pqstm
, exec
, ai_pqstm_exec
, ZEND_ACC_PUBLIC
)
1432 PHP_ME(pqstm
, desc
, ai_pqstm_desc
, ZEND_ACC_PUBLIC
)
1436 /* {{{ PHP_MINIT_FUNCTION
1438 PHP_MINIT_FUNCTION(pq
)
1440 zend_class_entry ce
= {0};
1441 php_pq_object_prophandler_t ph
= {0};
1443 zend_hash_init(&php_pqconn_object_prophandlers
, 1, NULL
, NULL
, 1);
1444 INIT_NS_CLASS_ENTRY(ce
, "pq", "Connection", php_pqconn_methods
);
1445 php_pqconn_class_entry
= zend_register_internal_class_ex(&ce
, NULL
, NULL TSRMLS_CC
);
1446 php_pqconn_class_entry
->create_object
= php_pqconn_create_object
;
1447 memcpy(&php_pqconn_object_handlers
, zend_get_std_object_handlers(), sizeof(zend_object_handlers
));
1448 php_pqconn_object_handlers
.read_property
= php_pqconn_object_read_prop
;
1449 php_pqconn_object_handlers
.write_property
= php_pqconn_object_write_prop
;
1450 php_pqconn_object_handlers
.clone_obj
= NULL
;
1451 php_pqconn_object_handlers
.get_property_ptr_ptr
= NULL
;
1453 zend_declare_property_long(php_pqconn_class_entry
, ZEND_STRL("status"), CONNECTION_BAD
, ZEND_ACC_PUBLIC TSRMLS_CC
);
1454 ph
.read
= php_pqconn_object_read_status
;
1455 zend_hash_add(&php_pqconn_object_prophandlers
, "status", sizeof("status"), (void *) &ph
, sizeof(ph
), NULL
);
1457 zend_declare_property_long(php_pqconn_class_entry
, ZEND_STRL("transactionStatus"), PQTRANS_UNKNOWN
, ZEND_ACC_PUBLIC TSRMLS_CC
);
1458 ph
.read
= php_pqconn_object_read_transaction_status
;
1459 zend_hash_add(&php_pqconn_object_prophandlers
, "transactionStatus", sizeof("transactionStatus"), (void *) &ph
, sizeof(ph
), NULL
);
1461 zend_declare_property_null(php_pqconn_class_entry
, ZEND_STRL("socket"), ZEND_ACC_PUBLIC TSRMLS_CC
);
1462 ph
.read
= NULL
; /* forward to std prophandler */
1463 zend_hash_add(&php_pqconn_object_prophandlers
, "socket", sizeof("socket"), (void *) &ph
, sizeof(ph
), NULL
);
1465 zend_declare_property_null(php_pqconn_class_entry
, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC TSRMLS_CC
);
1466 ph
.read
= php_pqconn_object_read_error_message
;
1467 zend_hash_add(&php_pqconn_object_prophandlers
, "errorMessage", sizeof("errorMessage"), (void *) &ph
, sizeof(ph
), NULL
);
1469 zend_declare_property_null(php_pqconn_class_entry
, ZEND_STRL("types"), ZEND_ACC_PUBLIC TSRMLS_CC
);
1470 ph
.read
= php_pqconn_object_read_types
;
1471 zend_hash_add(&php_pqconn_object_prophandlers
, "types", sizeof("types"), (void *) &ph
, sizeof(ph
), NULL
);
1473 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("OK"), CONNECTION_OK TSRMLS_CC
);
1474 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("BAD"), CONNECTION_BAD TSRMLS_CC
);
1475 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("STARTED"), CONNECTION_STARTED TSRMLS_CC
);
1476 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("MADE"), CONNECTION_MADE TSRMLS_CC
);
1477 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("AWAITING_RESPONSE"), CONNECTION_AWAITING_RESPONSE TSRMLS_CC
);
1478 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("AUTH_OK"), CONNECTION_AUTH_OK TSRMLS_CC
);
1479 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("SSL_STARTUP"), CONNECTION_SSL_STARTUP TSRMLS_CC
);
1480 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("SETENV"), CONNECTION_SETENV TSRMLS_CC
);
1482 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("TRANS_IDLE"), PQTRANS_IDLE TSRMLS_CC
);
1483 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("TRANS_ACTIVE"), PQTRANS_ACTIVE TSRMLS_CC
);
1484 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("TRANS_INTRANS"), PQTRANS_INTRANS TSRMLS_CC
);
1485 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("TRANS_INERROR"), PQTRANS_INERROR TSRMLS_CC
);
1486 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("TRANS_UNKNOWN"), PQTRANS_UNKNOWN TSRMLS_CC
);
1488 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("POLLING_FAILED"), PGRES_POLLING_FAILED TSRMLS_CC
);
1489 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("POLLING_READING"), PGRES_POLLING_READING TSRMLS_CC
);
1490 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("POLLING_WRITING"), PGRES_POLLING_WRITING TSRMLS_CC
);
1491 zend_declare_class_constant_long(php_pqconn_class_entry
, ZEND_STRL("POLLING_OK"), PGRES_POLLING_OK TSRMLS_CC
);
1493 zend_hash_init(&php_pqres_object_prophandlers
, 1, NULL
, NULL
, 1);
1494 memset(&ce
, 0, sizeof(ce
));
1495 INIT_NS_CLASS_ENTRY(ce
, "pq", "Result", php_pqres_methods
);
1496 php_pqres_class_entry
= zend_register_internal_class_ex(&ce
, NULL
, NULL TSRMLS_CC
);
1497 php_pqres_class_entry
->create_object
= php_pqres_create_object
;
1498 php_pqres_class_entry
->iterator_funcs
.funcs
= &php_pqres_iterator_funcs
;
1499 php_pqres_class_entry
->get_iterator
= php_pqres_iterator_init
;
1501 memcpy(&php_pqres_object_handlers
, zend_get_std_object_handlers(), sizeof(zend_object_handlers
));
1502 php_pqres_object_handlers
.read_property
= php_pqres_object_read_prop
;
1503 php_pqres_object_handlers
.write_property
= php_pqres_object_write_prop
;
1505 zend_declare_property_null(php_pqres_class_entry
, ZEND_STRL("status"), ZEND_ACC_PUBLIC TSRMLS_CC
);
1506 ph
.read
= php_pqres_object_read_status
;
1507 zend_hash_add(&php_pqres_object_prophandlers
, "status", sizeof("status"), (void *) &ph
, sizeof(ph
), NULL
);
1509 zend_declare_property_null(php_pqres_class_entry
, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC TSRMLS_CC
);
1510 ph
.read
= php_pqres_object_read_error_message
;
1511 zend_hash_add(&php_pqres_object_prophandlers
, "errorMessage", sizeof("errorMessage"), (void *) &ph
, sizeof(ph
), NULL
);
1513 zend_declare_property_long(php_pqres_class_entry
, ZEND_STRL("numRows"), 0, ZEND_ACC_PUBLIC TSRMLS_CC
);
1514 ph
.read
= php_pqres_object_read_num_rows
;
1515 zend_hash_add(&php_pqres_object_prophandlers
, "numRows", sizeof("numRows"), (void *) &ph
, sizeof(ph
), NULL
);
1517 zend_declare_property_long(php_pqres_class_entry
, ZEND_STRL("numCols"), 0, ZEND_ACC_PUBLIC TSRMLS_CC
);
1518 ph
.read
= php_pqres_object_read_num_cols
;
1519 zend_hash_add(&php_pqres_object_prophandlers
, "numCols", sizeof("numCols"), (void *) &ph
, sizeof(ph
), NULL
);
1521 zend_declare_property_long(php_pqres_class_entry
, ZEND_STRL("affectedRows"), 0, ZEND_ACC_PUBLIC TSRMLS_CC
);
1522 ph
.read
= php_pqres_object_read_affected_rows
;
1523 zend_hash_add(&php_pqres_object_prophandlers
, "affectedRows", sizeof("affectedRows"), (void *) &ph
, sizeof(ph
), NULL
);
1525 zend_declare_property_long(php_pqres_class_entry
, ZEND_STRL("fetchType"), PHP_PQRES_FETCH_ARRAY
, ZEND_ACC_PUBLIC TSRMLS_CC
);
1526 ph
.read
= php_pqres_object_read_fetch_type
;
1527 ph
.write
= php_pqres_object_write_fetch_type
;
1528 zend_hash_add(&php_pqres_object_prophandlers
, "fetchType", sizeof("fetchType"), (void *) &ph
, sizeof(ph
), NULL
);
1531 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("EMPTY_QUERY"), PGRES_EMPTY_QUERY TSRMLS_CC
);
1532 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("COMMAND_OK"), PGRES_COMMAND_OK TSRMLS_CC
);
1533 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("TUPLES_OK"), PGRES_TUPLES_OK TSRMLS_CC
);
1534 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("COPY_OUT"), PGRES_COPY_OUT TSRMLS_CC
);
1535 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("COPY_IN"), PGRES_COPY_IN TSRMLS_CC
);
1536 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("BAD_RESPONSE"), PGRES_BAD_RESPONSE TSRMLS_CC
);
1537 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("NONFATAL_ERROR"), PGRES_NONFATAL_ERROR TSRMLS_CC
);
1538 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("FATAL_ERROR"), PGRES_FATAL_ERROR TSRMLS_CC
);
1539 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("COPY_BOTH"), PGRES_COPY_BOTH TSRMLS_CC
);
1540 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("SINGLE_TUPLE"), PGRES_SINGLE_TUPLE TSRMLS_CC
);
1542 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("FETCH_ARRAY"), PHP_PQRES_FETCH_ARRAY TSRMLS_CC
);
1543 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("FETCH_ASSOC"), PHP_PQRES_FETCH_ASSOC TSRMLS_CC
);
1544 zend_declare_class_constant_long(php_pqres_class_entry
, ZEND_STRL("FETCH_OBJECT"), PHP_PQRES_FETCH_OBJECT TSRMLS_CC
);
1546 zend_hash_init(&php_pqstm_object_prophandlers
, 1, NULL
, NULL
, 1);
1547 memset(&ce
, 0, sizeof(ce
));
1548 INIT_NS_CLASS_ENTRY(ce
, "pq", "Statement", php_pqstm_methods
);
1549 php_pqstm_class_entry
= zend_register_internal_class_ex(&ce
, NULL
, NULL TSRMLS_CC
);
1550 php_pqstm_class_entry
->create_object
= php_pqstm_create_object
;
1552 memcpy(&php_pqstm_object_handlers
, zend_get_std_object_handlers(), sizeof(zend_object_handlers
));
1553 php_pqstm_object_handlers
.read_property
= php_pqstm_object_read_prop
;
1554 php_pqstm_object_handlers
.write_property
= php_pqstm_object_write_prop
;
1556 zend_declare_property_null(php_pqstm_class_entry
, ZEND_STRL("name"), ZEND_ACC_PUBLIC TSRMLS_CC
);
1557 ph
.read
= php_pqstm_object_read_name
;
1558 zend_hash_add(&php_pqstm_object_prophandlers
, "name", sizeof("name"), (void *) &ph
, sizeof(ph
), NULL
);
1560 zend_declare_property_null(php_pqstm_class_entry
, ZEND_STRL("connection"), ZEND_ACC_PUBLIC TSRMLS_CC
);
1561 ph
.read
= php_pqstm_object_read_connection
;
1562 zend_hash_add(&php_pqstm_object_prophandlers
, "connection", sizeof("connection"), (void *) &ph
, sizeof(ph
), NULL
);
1565 REGISTER_INI_ENTRIES();
1571 /* {{{ PHP_MSHUTDOWN_FUNCTION
1573 PHP_MSHUTDOWN_FUNCTION(pq
)
1575 /* uncomment this line if you have INI entries
1576 UNREGISTER_INI_ENTRIES();
1582 /* {{{ PHP_MINFO_FUNCTION
1584 PHP_MINFO_FUNCTION(pq
)
1586 php_info_print_table_start();
1587 php_info_print_table_header(2, "pq support", "enabled");
1588 php_info_print_table_end();
1590 /* Remove comments if you have entries in php.ini
1591 DISPLAY_INI_ENTRIES();
1603 * vim600: noet sw=4 ts=4 fdm=marker
1604 * vim<600: noet sw=4 ts=4