split source
[m6w6/ext-pq] / src / php_pqconn_event.c
diff --git a/src/php_pqconn_event.c b/src/php_pqconn_event.c
new file mode 100644 (file)
index 0000000..2c4461a
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+    +--------------------------------------------------------------------+
+    | PECL :: pq                                                         |
+    +--------------------------------------------------------------------+
+    | Redistribution and use in source and binary forms, with or without |
+    | modification, are permitted provided that the conditions mentioned |
+    | in the accompanying LICENSE file are met.                          |
+    +--------------------------------------------------------------------+
+    | Copyright (c) 2013, Michael Wallner <mike@php.net>                 |
+    +--------------------------------------------------------------------+
+*/
+
+#ifdef HAVE_CONFIG_H
+#      include "config.h"
+#endif
+
+#include <php.h>
+
+#include <libpq-events.h>
+
+#include "php_pq.h"
+#include "php_pq_misc.h"
+#include "php_pq_object.h"
+#include "php_pqconn_event.h"
+#include "php_pqres.h"
+
+static int apply_event(void *p, void *a TSRMLS_DC)
+{
+       php_pq_callback_t *cb = p;
+       zval *args = a;
+       zval *retval = NULL;
+
+       zend_fcall_info_args(&cb->fci, args TSRMLS_CC);
+       zend_fcall_info_call(&cb->fci, &cb->fcc, &retval, NULL TSRMLS_CC);
+       if (retval) {
+               zval_ptr_dtor(&retval);
+       }
+
+       return ZEND_HASH_APPLY_KEEP;
+}
+
+static void php_pqconn_event_connreset(PGEventConnReset *event)
+{
+       php_pqconn_event_data_t *data = PQinstanceData(event->conn, php_pqconn_event);
+
+       if (data) {
+               HashTable *evhs;
+               TSRMLS_DF(data);
+
+               if (SUCCESS == zend_hash_find(&data->obj->intern->eventhandlers, ZEND_STRS("reset"), (void *) &evhs)) {
+                       zval *args, *connection = NULL;
+
+                       MAKE_STD_ZVAL(args);
+                       array_init(args);
+                       php_pq_object_to_zval(data->obj, &connection TSRMLS_CC);
+                       add_next_index_zval(args, connection);
+                       zend_hash_apply_with_argument(evhs, apply_event, args TSRMLS_CC);
+                       zval_ptr_dtor(&args);
+               }
+       }
+}
+
+static void php_pqconn_event_resultcreate(PGEventResultCreate *event)
+{
+       php_pqconn_event_data_t *data = PQinstanceData(event->conn, php_pqconn_event);
+
+       if (data) {
+               php_pqres_object_t *obj;
+               HashTable *evhs;
+               TSRMLS_DF(data);
+
+               php_pqres_init_instance_data(event->result, &obj TSRMLS_CC);
+
+               /* event listener */
+               if (SUCCESS == zend_hash_find(&data->obj->intern->eventhandlers, ZEND_STRS("result"), (void *) &evhs)) {
+                       zval *args, *connection = NULL, *res = NULL;
+
+                       MAKE_STD_ZVAL(args);
+                       array_init(args);
+                       php_pq_object_to_zval(data->obj, &connection TSRMLS_CC);
+                       add_next_index_zval(args, connection);
+                       php_pq_object_to_zval(obj, &res TSRMLS_CC);
+                       add_next_index_zval(args, res);
+                       zend_hash_apply_with_argument(evhs, apply_event, args TSRMLS_CC);
+                       zval_ptr_dtor(&args);
+               }
+
+               /* async callback */
+               if (data->obj->intern->onevent.fci.size > 0) {
+                       zval *res = NULL;
+
+                       php_pq_object_to_zval(obj, &res TSRMLS_CC);
+                       zend_fcall_info_argn(&data->obj->intern->onevent.fci TSRMLS_CC, 1, &res);
+                       zend_fcall_info_call(&data->obj->intern->onevent.fci, &data->obj->intern->onevent.fcc, NULL, NULL TSRMLS_CC);
+                       zval_ptr_dtor(&res);
+               }
+
+       }
+}
+
+static void php_pqconn_event_resultdestroy(PGEventResultDestroy *event)
+{
+       php_pqres_object_t *obj = PQresultInstanceData(event->result, php_pqconn_event);
+
+       if (obj) {
+               obj->intern->res = NULL;
+       }
+}
+
+int php_pqconn_event(PGEventId id, void *e, void *data)
+{
+       switch (id) {
+       case PGEVT_CONNRESET:
+               php_pqconn_event_connreset(e);
+               break;
+       case PGEVT_RESULTCREATE:
+               php_pqconn_event_resultcreate(e);
+               break;
+       case PGEVT_RESULTDESTROY:
+               php_pqconn_event_resultdestroy(e);
+               break;
+       default:
+               break;
+       }
+
+       return 1;
+}
+
+php_pqconn_event_data_t *php_pqconn_event_data_init(php_pqconn_object_t *obj TSRMLS_DC)
+{
+       php_pqconn_event_data_t *data = emalloc(sizeof(*data));
+
+       data->obj = obj;
+       TSRMLS_CF(data);
+
+       return data;
+}
+
+void php_pqconn_notice_recv(void *p, const PGresult *res)
+{
+       php_pqconn_event_data_t *data = p;
+
+       if (data) {
+               HashTable *evhs;
+               TSRMLS_DF(data);
+
+               if (SUCCESS == zend_hash_find(&data->obj->intern->eventhandlers, ZEND_STRS("notice"), (void *) &evhs)) {
+                       zval *args, *connection = NULL;
+
+                       MAKE_STD_ZVAL(args);
+                       array_init(args);
+                       php_pq_object_to_zval(data->obj, &connection TSRMLS_CC);
+                       add_next_index_zval(args, connection);
+                       add_next_index_string(args, PHP_PQresultErrorMessage(res), 1);
+                       zend_hash_apply_with_argument(evhs, apply_event, args TSRMLS_CC);
+                       zval_ptr_dtor(&args);
+               }
+       }
+}
+
+void php_pqconn_notice_ignore(void *p, const PGresult *res)
+{
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */