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 +--------------------------------------------------------------------+
19 #define SMART_STR_PREALLOC 256
20 #include <ext/standard/php_smart_str.h>
22 #include <libpq-events.h>
25 #include "php_pq_misc.h"
26 #include "php_pq_object.h"
27 #include "php_pqconn_event.h"
28 #include "php_pqstm.h"
29 #include "php_pqres.h"
31 static int apply_event(void *p
, void *a TSRMLS_DC
)
33 php_pq_callback_t
*cb
= p
;
37 zend_fcall_info_args(&cb
->fci
, args TSRMLS_CC
);
38 zend_fcall_info_call(&cb
->fci
, &cb
->fcc
, &retval
, NULL TSRMLS_CC
);
40 zval_ptr_dtor(&retval
);
43 return ZEND_HASH_APPLY_KEEP
;
47 static inline PGresult
*relisten(PGconn
*conn
, const char *channel_str
, size_t channel_len TSRMLS_DC
)
49 char *quoted_channel
= PQescapeIdentifier(conn
, channel_str
, channel_len
);
55 smart_str_appends(&cmd
, "LISTEN ");
56 smart_str_appends(&cmd
, quoted_channel
);
59 res
= PQexec(conn
, cmd
.c
);
62 PQfreemem(quoted_channel
);
68 static int apply_relisten(void *p TSRMLS_DC
, int argc
, va_list argv
, zend_hash_key
*key
)
70 php_pqconn_object_t
*obj
= va_arg(argv
, php_pqconn_object_t
*);
71 PGresult
*res
= relisten(obj
->intern
->conn
, key
->arKey
, key
->nKeyLength
- 1 TSRMLS_CC
);
77 return ZEND_HASH_APPLY_KEEP
;
80 static int apply_reprepare(void *p TSRMLS_DC
, int argc
, va_list argv
, zend_hash_key
*key
)
82 php_pqconn_object_t
*obj
= va_arg(argv
, php_pqconn_object_t
*);
83 php_pqstm_t
*stm
= *(php_pqstm_object_t
**) p
;
85 php_pqconn_prepare(NULL
, obj
, stm
->name
, stm
->query
, stm
->params TSRMLS_CC
);
87 return ZEND_HASH_APPLY_KEEP
;
90 static void php_pqconn_event_connreset(PGEventConnReset
*event
)
92 php_pqconn_event_data_t
*data
= PQinstanceData(event
->conn
, php_pqconn_event
);
98 /* restore listeners */
99 zend_hash_apply_with_arguments(&data
->obj
->intern
->listeners TSRMLS_CC
, apply_relisten
, 1, data
->obj
);
101 /* restore statements */
102 zend_hash_apply_with_arguments(&data
->obj
->intern
->statements TSRMLS_CC
, apply_reprepare
, 1, data
->obj
);
105 if (SUCCESS
== zend_hash_find(&data
->obj
->intern
->eventhandlers
, ZEND_STRS("reset"), (void *) &evhs
)) {
106 zval
*args
, *connection
= NULL
;
110 php_pq_object_to_zval(data
->obj
, &connection TSRMLS_CC
);
111 add_next_index_zval(args
, connection
);
112 zend_hash_apply_with_argument(evhs
, apply_event
, args TSRMLS_CC
);
113 zval_ptr_dtor(&args
);
118 static void php_pqconn_event_resultcreate(PGEventResultCreate
*event
)
120 php_pqconn_event_data_t
*data
= PQinstanceData(event
->conn
, php_pqconn_event
);
123 php_pqres_object_t
*obj
;
127 php_pqres_init_instance_data(event
->result
, data
->obj
, &obj TSRMLS_CC
);
130 if (SUCCESS
== zend_hash_find(&data
->obj
->intern
->eventhandlers
, ZEND_STRS("result"), (void *) &evhs
)) {
131 zval
*args
, *connection
= NULL
, *res
= NULL
;
135 php_pq_object_to_zval(data
->obj
, &connection TSRMLS_CC
);
136 add_next_index_zval(args
, connection
);
137 php_pq_object_to_zval(obj
, &res TSRMLS_CC
);
138 add_next_index_zval(args
, res
);
139 zend_hash_apply_with_argument(evhs
, apply_event
, args TSRMLS_CC
);
140 zval_ptr_dtor(&args
);
144 if (php_pq_callback_is_enabled(&data
->obj
->intern
->onevent
)) {
147 php_pq_object_to_zval(obj
, &res TSRMLS_CC
);
148 zend_fcall_info_argn(&data
->obj
->intern
->onevent
.fci TSRMLS_CC
, 1, &res
);
149 zend_fcall_info_call(&data
->obj
->intern
->onevent
.fci
, &data
->obj
->intern
->onevent
.fcc
, NULL
, NULL TSRMLS_CC
);
156 static void php_pqconn_event_resultdestroy(PGEventResultDestroy
*event
)
158 php_pqres_object_t
*obj
= PQresultInstanceData(event
->result
, php_pqconn_event
);
161 obj
->intern
->res
= NULL
;
165 int php_pqconn_event(PGEventId id
, void *e
, void *data
)
168 case PGEVT_CONNRESET
:
169 php_pqconn_event_connreset(e
);
171 case PGEVT_RESULTCREATE
:
172 php_pqconn_event_resultcreate(e
);
174 case PGEVT_RESULTDESTROY
:
175 php_pqconn_event_resultdestroy(e
);
184 php_pqconn_event_data_t
*php_pqconn_event_data_init(php_pqconn_object_t
*obj TSRMLS_DC
)
186 php_pqconn_event_data_t
*data
= emalloc(sizeof(*data
));
194 void php_pqconn_notice_recv(void *p
, const PGresult
*res
)
196 php_pqconn_event_data_t
*data
= p
;
202 if (SUCCESS
== zend_hash_find(&data
->obj
->intern
->eventhandlers
, ZEND_STRS("notice"), (void *) &evhs
)) {
203 zval
*args
, *connection
= NULL
;
207 php_pq_object_to_zval(data
->obj
, &connection TSRMLS_CC
);
208 add_next_index_zval(args
, connection
);
209 add_next_index_string(args
, PHP_PQresultErrorMessage(res
), 1);
210 zend_hash_apply_with_argument(evhs
, apply_event
, args TSRMLS_CC
);
211 zval_ptr_dtor(&args
);
216 void php_pqconn_notice_ignore(void *p
, const PGresult
*res
)
225 * vim600: noet sw=4 ts=4 fdm=marker
226 * vim<600: noet sw=4 ts=4