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 #include <Zend/zend_smart_str.h>
21 #include <libpq-events.h>
24 #include "php_pq_misc.h"
25 #include "php_pq_object.h"
26 #include "php_pqconn_event.h"
27 #include "php_pqstm.h"
28 #include "php_pqres.h"
30 static int apply_event(zval
*p
, void *a
)
32 php_pq_callback_t
*cb
= Z_PTR_P(p
);
37 zend_fcall_info_args(&cb
->fci
, args
);
38 zend_fcall_info_call(&cb
->fci
, &cb
->fcc
, &rv
, NULL
);
39 zend_fcall_info_args_clear(&cb
->fci
, 0);
42 return ZEND_HASH_APPLY_KEEP
;
46 static inline PGresult
*relisten(PGconn
*conn
, const char *channel_str
, size_t channel_len
)
48 char *quoted_channel
= PQescapeIdentifier(conn
, channel_str
, channel_len
);
54 smart_str_appends(&cmd
, "LISTEN ");
55 smart_str_appends(&cmd
, quoted_channel
);
58 res
= PQexec(conn
, smart_str_v(&cmd
));
61 PQfreemem(quoted_channel
);
67 static int apply_relisten(zval
*p
, int argc
, va_list argv
, zend_hash_key
*key
)
69 php_pqconn_object_t
*obj
= va_arg(argv
, php_pqconn_object_t
*);
70 PGresult
*res
= relisten(obj
->intern
->conn
, key
->key
->val
, key
->key
->len
);
76 return ZEND_HASH_APPLY_KEEP
;
79 static int apply_reprepare(zval
*p
, int argc
, va_list argv
, zend_hash_key
*key
)
81 php_pqconn_object_t
*obj
= va_arg(argv
, php_pqconn_object_t
*);
82 php_pqstm_t
*stm
= Z_PTR_P(p
);
84 php_pqconn_prepare(NULL
, obj
, stm
->name
, stm
->query
, stm
->params
);
86 return ZEND_HASH_APPLY_KEEP
;
89 static void php_pqconn_event_connreset(PGEventConnReset
*event
)
91 php_pqconn_event_data_t
*data
= PQinstanceData(event
->conn
, php_pqconn_event
);
96 /* restore listeners */
97 zend_hash_apply_with_arguments(&data
->obj
->intern
->listeners
, apply_relisten
, 1, data
->obj
);
99 /* restore statements */
100 zend_hash_apply_with_arguments(&data
->obj
->intern
->statements
, apply_reprepare
, 1, data
->obj
);
103 if ((zevhs
= zend_hash_str_find(&data
->obj
->intern
->eventhandlers
, ZEND_STRL("reset")))) {
104 zval args
, connection
;
107 php_pq_object_to_zval(data
->obj
, &connection
);
108 add_next_index_zval(&args
, &connection
);
109 zend_hash_apply_with_argument(Z_ARRVAL_P(zevhs
), apply_event
, &args
);
110 zval_ptr_dtor(&args
);
115 static void php_pqconn_event_resultcreate(PGEventResultCreate
*event
)
117 php_pqconn_event_data_t
*data
= PQinstanceData(event
->conn
, php_pqconn_event
);
120 php_pqres_object_t
*obj
= php_pqres_init_instance_data(event
->result
, data
->obj
);
124 if ((zevhs
= zend_hash_str_find(&data
->obj
->intern
->eventhandlers
, ZEND_STRL("result")))) {
125 zval args
, connection
, res
;
128 php_pq_object_to_zval(data
->obj
, &connection
);
129 add_next_index_zval(&args
, &connection
);
130 php_pq_object_to_zval(obj
, &res
);
131 add_next_index_zval(&args
, &res
);
132 zend_hash_apply_with_argument(Z_ARRVAL_P(zevhs
), apply_event
, &args
);
133 zval_ptr_dtor(&args
);
137 if (php_pq_callback_is_enabled(&data
->obj
->intern
->onevent
)) {
140 php_pq_object_to_zval(obj
, &res
);
141 zend_fcall_info_argn(&data
->obj
->intern
->onevent
.fci
, 1, &res
);
142 zend_fcall_info_call(&data
->obj
->intern
->onevent
.fci
, &data
->obj
->intern
->onevent
.fcc
, NULL
, NULL
);
149 static void php_pqconn_event_resultdestroy(PGEventResultDestroy
*event
)
151 php_pqres_object_t
*obj
= PQresultInstanceData(event
->result
, php_pqconn_event
);
154 obj
->intern
->res
= NULL
;
155 assert(GC_REFCOUNT(&obj
->zo
));
156 php_pq_object_delref(obj
);
160 int php_pqconn_event(PGEventId id
, void *e
, void *data
)
163 case PGEVT_CONNRESET
:
164 php_pqconn_event_connreset(e
);
166 case PGEVT_RESULTCREATE
:
167 php_pqconn_event_resultcreate(e
);
169 case PGEVT_RESULTDESTROY
:
170 php_pqconn_event_resultdestroy(e
);
179 php_pqconn_event_data_t
*php_pqconn_event_data_init(php_pqconn_object_t
*obj
)
181 php_pqconn_event_data_t
*data
= emalloc(sizeof(*data
));
189 void php_pqconn_notice_recv(void *p
, const PGresult
*res
)
191 php_pqconn_event_data_t
*data
= p
;
196 if ((zevhs
= zend_hash_str_find(&data
->obj
->intern
->eventhandlers
, ZEND_STRL("notice")))) {
197 zval args
, connection
;
200 php_pq_object_to_zval(data
->obj
, &connection
);
201 add_next_index_zval(&args
, &connection
);
202 add_next_index_string(&args
, PHP_PQresultErrorMessage(res
));
203 zend_hash_apply_with_argument(Z_ARRVAL_P(zevhs
), apply_event
, &args
);
204 zval_ptr_dtor(&args
);
209 void php_pqconn_notice_ignore(void *p
, const PGresult
*res
)
218 * vim600: noet sw=4 ts=4 fdm=marker
219 * vim<600: noet sw=4 ts=4