prepare v2.2.3
[m6w6/ext-pq] / src / php_pqconn.c
index 07c907f59e117f5d80d81fff5c7b1045adbf93f5..19ea6f05ebcaebd0abb059d475c7bad802f29128 100644 (file)
@@ -42,7 +42,7 @@ static void php_pq_callback_hash_dtor(zval *p)
 }
 
 /*
-static void php_pqconn_del_eventhandler(php_pqconn_object_t *obj, const char *type_str, size_t type_len, ulong id)
+static void php_pqconn_del_eventhandler(php_pqconn_object_t *obj, const char *type_str, size_t type_len, unsigned long id)
 {
        zval **evhs;
 
@@ -86,6 +86,7 @@ static void php_pqconn_object_free(zend_object *o)
                php_resource_factory_handle_dtor(&obj->intern->factory, obj->intern->conn);
                php_resource_factory_dtor(&obj->intern->factory);
                zend_hash_destroy(&obj->intern->listeners);
+               zend_hash_destroy(&obj->intern->statements);
                zend_hash_destroy(&obj->intern->converters);
                zend_hash_destroy(&obj->intern->eventhandlers);
                efree(obj->intern);
@@ -106,21 +107,21 @@ static zend_object *php_pqconn_create_object(zend_class_entry *class_type)
        return &php_pqconn_create_object_ex(class_type, NULL)->zo;
 }
 
-static void php_pqconn_object_read_status(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_status(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
 
        RETVAL_LONG(PQstatus(obj->intern->conn));
 }
 
-static void php_pqconn_object_read_transaction_status(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_transaction_status(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
 
        RETVAL_LONG(PQtransactionStatus(obj->intern->conn));
 }
 
-static void php_pqconn_object_read_error_message(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_error_message(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
        char *error = PHP_PQerrorMessage(obj->intern->conn);
@@ -175,21 +176,21 @@ void php_pqconn_notify_listeners(php_pqconn_object_t *obj)
        }
 }
 
-static void php_pqconn_object_read_busy(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_busy(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
 
        RETVAL_BOOL(PQisBusy(obj->intern->conn));
 }
 
-static void php_pqconn_object_read_encoding(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_encoding(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
 
        RETVAL_STRING(pg_encoding_to_char(PQclientEncoding(obj->intern->conn)));
 }
 
-static void php_pqconn_object_write_encoding(zval *object, void *o, zval *value)
+static void php_pqconn_object_write_encoding(void *o, zval *value)
 {
        php_pqconn_object_t *obj = o;
        zend_string *zenc = zval_get_string(value);
@@ -201,21 +202,35 @@ static void php_pqconn_object_write_encoding(zval *object, void *o, zval *value)
        zend_string_release(zenc);
 }
 
-static void php_pqconn_object_read_unbuffered(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_unbuffered(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
 
        RETVAL_BOOL(obj->intern->unbuffered);
 }
 
-static void php_pqconn_object_write_unbuffered(zval *object, void *o, zval *value)
+static void php_pqconn_object_write_unbuffered(void *o, zval *value)
 {
        php_pqconn_object_t *obj = o;
 
        obj->intern->unbuffered = z_is_true(value);
 }
 
-static void php_pqconn_object_read_db(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_nonblocking(void *o, zval *return_value)
+{
+       php_pqconn_object_t *obj = o;
+
+       RETVAL_BOOL(PQisnonblocking(obj->intern->conn));
+}
+
+static void php_pqconn_object_write_nonblocking(void *o, zval *value)
+{
+       php_pqconn_object_t *obj = o;
+
+       PQsetnonblocking(obj->intern->conn, z_is_true(value));
+}
+
+static void php_pqconn_object_read_db(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
        char *db = PQdb(obj->intern->conn);
@@ -227,7 +242,7 @@ static void php_pqconn_object_read_db(zval *object, void *o, zval *return_value)
        }
 }
 
-static void php_pqconn_object_read_user(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_user(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
        char *user = PQuser(obj->intern->conn);
@@ -239,7 +254,7 @@ static void php_pqconn_object_read_user(zval *object, void *o, zval *return_valu
        }
 }
 
-static void php_pqconn_object_read_pass(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_pass(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
        char *pass = PQpass(obj->intern->conn);
@@ -251,7 +266,7 @@ static void php_pqconn_object_read_pass(zval *object, void *o, zval *return_valu
        }
 }
 
-static void php_pqconn_object_read_host(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_host(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
        char *host = PQhost(obj->intern->conn);
@@ -263,7 +278,7 @@ static void php_pqconn_object_read_host(zval *object, void *o, zval *return_valu
        }
 }
 
-static void php_pqconn_object_read_port(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_port(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
        char *port = PQport(obj->intern->conn);
@@ -276,7 +291,7 @@ static void php_pqconn_object_read_port(zval *object, void *o, zval *return_valu
 }
 
 #if HAVE_PQCONNINFO
-static void php_pqconn_object_read_params(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_params(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
        PQconninfoOption *ptr, *params = PQconninfo(obj->intern->conn);
@@ -296,7 +311,7 @@ static void php_pqconn_object_read_params(zval *object, void *o, zval *return_va
 }
 #endif
 
-static void php_pqconn_object_read_options(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_options(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
        char *options = PQoptions(obj->intern->conn);
@@ -335,7 +350,7 @@ static int apply_read_callbacks(zval *p, int argc, va_list argv, zend_hash_key *
 
        return ZEND_HASH_APPLY_KEEP;
 }
-static void php_pqconn_object_read_event_handlers(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_event_handlers(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
 
@@ -343,7 +358,7 @@ static void php_pqconn_object_read_event_handlers(zval *object, void *o, zval *r
        zend_hash_apply_with_arguments(&obj->intern->eventhandlers, apply_read_callbacks, 1, Z_ARRVAL_P(return_value));
 }
 
-static void php_pqconn_object_gc_event_handlers(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_gc_event_handlers(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
        zval *evhs;
@@ -363,7 +378,7 @@ static void php_pqconn_object_gc_event_handlers(zval *object, void *o, zval *ret
        ZEND_HASH_FOREACH_END();
 }
 
-static void php_pqconn_object_read_listeners(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_listeners(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
 
@@ -371,7 +386,7 @@ static void php_pqconn_object_read_listeners(zval *object, void *o, zval *return
        zend_hash_apply_with_arguments(&obj->intern->listeners, apply_read_callbacks, 1, Z_ARRVAL_P(return_value));
 }
 
-static void php_pqconn_object_gc_listeners(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_gc_listeners(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
        zval *listeners;
@@ -391,7 +406,7 @@ static void php_pqconn_object_gc_listeners(zval *object, void *o, zval *return_v
        ZEND_HASH_FOREACH_END();
 }
 
-static void php_pqconn_object_read_converters(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_converters(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
 
@@ -399,7 +414,7 @@ static void php_pqconn_object_read_converters(zval *object, void *o, zval *retur
        zend_hash_copy(Z_ARRVAL_P(return_value), &obj->intern->converters, zval_add_ref);
 }
 
-static void php_pqconn_object_gc_converters(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_gc_converters(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
        zval *converter;
@@ -411,71 +426,99 @@ static void php_pqconn_object_gc_converters(zval *object, void *o, zval *return_
        ZEND_HASH_FOREACH_END();
 }
 
-static void php_pqconn_object_read_def_fetch_type(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_def_fetch_type(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
 
        RETVAL_LONG(obj->intern->default_fetch_type);
 }
-static void php_pqconn_object_write_def_fetch_type(zval *object, void *o, zval *value)
+static void php_pqconn_object_write_def_fetch_type(void *o, zval *value)
 {
        php_pqconn_object_t *obj = o;
 
        obj->intern->default_fetch_type = zval_get_long(value) & 0x3; /* two bits only */
 }
 
-static void php_pqconn_object_read_def_txn_isolation(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_def_txn_isolation(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
 
        RETVAL_LONG(obj->intern->default_txn_isolation);
 }
-static void php_pqconn_object_write_def_txn_isolation(zval *object, void *o, zval *value)
+static void php_pqconn_object_write_def_txn_isolation(void *o, zval *value)
 {
        php_pqconn_object_t *obj = o;
 
        obj->intern->default_txn_isolation = zval_get_long(value) & 0x3; /* two bits only */
 }
 
-static void php_pqconn_object_read_def_txn_readonly(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_def_txn_readonly(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
 
        RETVAL_BOOL(obj->intern->default_txn_readonly);
 }
-static void php_pqconn_object_write_def_txn_readonly(zval *object, void *o, zval *value)
+static void php_pqconn_object_write_def_txn_readonly(void *o, zval *value)
 {
        php_pqconn_object_t *obj = o;
 
        obj->intern->default_txn_readonly = z_is_true(value);
 }
 
-static void php_pqconn_object_read_def_txn_deferrable(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_def_txn_deferrable(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
 
        RETVAL_BOOL(obj->intern->default_txn_deferrable);
 }
-static void php_pqconn_object_write_def_txn_deferrable(zval *object, void *o, zval *value)
+static void php_pqconn_object_write_def_txn_deferrable(void *o, zval *value)
 {
        php_pqconn_object_t *obj = o;
 
        obj->intern->default_txn_deferrable = zend_is_true(value);
 }
 
-static void php_pqconn_object_read_def_auto_conv(zval *object, void *o, zval *return_value)
+static void php_pqconn_object_read_def_auto_conv(void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
 
        RETVAL_LONG(obj->intern->default_auto_convert);
 }
-static void php_pqconn_object_write_def_auto_conv(zval*object, void *o, zval *value)
+static void php_pqconn_object_write_def_auto_conv(void *o, zval *value)
 {
        php_pqconn_object_t *obj = o;
 
        obj->intern->default_auto_convert = zval_get_long(value) & PHP_PQRES_CONV_ALL;
 }
 
+#ifdef HAVE_PQLIBVERSION
+static void php_pqconn_object_read_lib_version(void *o, zval *return_value)
+{
+       char ver[16];
+
+       php_pq_version_to_string(PQlibVersion(), ver, sizeof(ver));
+       RETVAL_STRING(ver);
+}
+#endif
+#ifdef HAVE_PQPROTOCOLVERSION
+static void php_pqconn_object_read_protocol_version(void *o, zval *return_value)
+{
+       php_pqconn_object_t *obj = o;
+
+       RETVAL_LONG(PQprotocolVersion(obj->intern->conn));
+}
+#endif
+#ifdef HAVE_PQSERVERVERSION
+static void php_pqconn_object_read_server_version(void *o, zval *return_value)
+{
+       php_pqconn_object_t *obj = o;
+       char ver[16];
+
+       php_pq_version_to_string(PQserverVersion(obj->intern->conn), ver, sizeof(ver));
+       RETVAL_STRING(ver);
+}
+#endif
+
 static ZEND_RESULT_CODE php_pqconn_update_socket(zval *zobj, php_pqconn_object_t *obj)
 {
        zval zsocket, zmember;
@@ -499,7 +542,11 @@ static ZEND_RESULT_CODE php_pqconn_update_socket(zval *zobj, php_pqconn_object_t
                ZVAL_NULL(&zsocket);
                retval = FAILURE;
        }
-       zend_get_std_object_handlers()->write_property(zobj, &zmember, &zsocket, NULL);
+#if PHP_VERSION_ID >= 80000
+       zend_std_write_property(Z_OBJ_P(zobj), Z_STR(zmember), &zsocket, NULL);
+#else
+       zend_std_write_property(zobj, &zmember, &zsocket, NULL);
+#endif
        zval_ptr_dtor(&zsocket);
        zval_ptr_dtor(&zmember);
 
@@ -552,7 +599,7 @@ php_resource_factory_ops_t *php_pqconn_get_resource_factory_ops(void)
 static void php_pqconn_wakeup(php_persistent_handle_factory_t *f, void **handle)
 {
        PGresult *res = PQexec(*handle, "");
-       php_pq_clear_res(res);
+       php_pqres_clear(res);
 
        if (CONNECTION_OK != PQstatus(*handle)) {
                PQreset(*handle);
@@ -571,7 +618,7 @@ static inline PGresult *unlisten(PGconn *conn, const char *channel_str, size_t c
                smart_str_appends(&cmd, quoted_channel);
                smart_str_0(&cmd);
 
-               res = PQexec(conn, smart_str_v(&cmd));
+               res = php_pq_exec(conn, smart_str_v(&cmd));
 
                smart_str_free(&cmd);
                PQfreemem(quoted_channel);
@@ -586,7 +633,7 @@ static int apply_unlisten(zval *p, int argc, va_list argv, zend_hash_key *key)
        PGresult *res = unlisten(obj->intern->conn, key->key->val, key->key->len);
 
        if (res) {
-               php_pq_clear_res(res);
+               php_pqres_clear(res);
        }
 
        return ZEND_HASH_APPLY_REMOVE;
@@ -613,7 +660,7 @@ static void php_pqconn_retire(php_persistent_handle_factory_t *f, void **handle)
        }
        /* clean up async results */
        while ((res = PQgetResult(*handle))) {
-               php_pq_clear_res(res);
+               php_pqres_clear(res);
        }
 
        /* clean up transaction & session */
@@ -627,7 +674,7 @@ static void php_pqconn_retire(php_persistent_handle_factory_t *f, void **handle)
        }
 
        if (res) {
-               php_pq_clear_res(res);
+               php_pqres_clear(res);
        }
 
        if (evdata) {
@@ -668,6 +715,7 @@ static PHP_METHOD(pqconn, __construct) {
                        obj->intern->default_auto_convert = PHP_PQRES_CONV_ALL;
 
                        zend_hash_init(&obj->intern->listeners, 0, NULL, ZVAL_PTR_DTOR, 0);
+                       zend_hash_init(&obj->intern->statements, 0, NULL, NULL, 0);
                        zend_hash_init(&obj->intern->converters, 0, NULL, ZVAL_PTR_DTOR, 0);
                        zend_hash_init(&obj->intern->eventhandlers, 0, NULL, ZVAL_PTR_DTOR, 0);
 
@@ -774,7 +822,7 @@ static PHP_METHOD(pqconn, unlisten)
 
                        if (res) {
                                php_pqres_success(res);
-                               php_pq_clear_res(res);
+                               php_pqres_clear(res);
                        }
                }
        }
@@ -854,7 +902,7 @@ static PHP_METHOD(pqconn, listen) {
        zend_error_handling zeh;
        char *channel_str = NULL;
        size_t channel_len = 0;
-       php_pq_callback_t listener = {{0}};
+       php_pq_callback_t listener = PHP_PQ_CALLBACK_INIT;
        ZEND_RESULT_CODE rv;
 
        zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
@@ -891,7 +939,7 @@ static PHP_METHOD(pqconn, listen) {
                                                obj->intern->poller = PQconsumeInput;
                                                php_pqconn_add_listener(obj, channel_str, channel_len, &listener);
                                        }
-                                       php_pq_clear_res(res);
+                                       php_pqres_clear(res);
                                }
 
                                php_pqconn_notify_listeners(obj);
@@ -908,7 +956,7 @@ static PHP_METHOD(pqconn, listenAsync) {
        zend_error_handling zeh;
        char *channel_str = NULL;
        size_t channel_len = 0;
-       php_pq_callback_t listener = {{0}};
+       php_pq_callback_t listener = PHP_PQ_CALLBACK_INIT;
        ZEND_RESULT_CODE rv;
 
        zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
@@ -970,13 +1018,13 @@ static PHP_METHOD(pqconn, notify) {
                        PGresult *res;
                        char *params[2] = {channel_str, message_str};
 
-                       res = PQexecParams(obj->intern->conn, "select pg_notify($1, $2)", 2, NULL, (const char *const*) params, NULL, NULL, 0);
+                       res = php_pq_exec_params(obj->intern->conn, "select pg_notify($1, $2)", 2, NULL, (const char *const*) params, NULL, NULL, 0);
 
                        if (!res) {
                                throw_exce(EX_RUNTIME, "Failed to notify listeners (%s)", PHP_PQerrorMessage(obj->intern->conn));
                        } else {
                                php_pqres_success(res);
-                               php_pq_clear_res(res);
+                               php_pqres_clear(res);
                        }
 
                        php_pqconn_notify_listeners(obj);
@@ -1045,6 +1093,40 @@ static PHP_METHOD(pqconn, poll) {
        }
 }
 
+ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_flush, 0, 0, 0)
+ZEND_END_ARG_INFO();
+static PHP_METHOD(pqconn, flush) {
+       zend_error_handling zeh;
+       ZEND_RESULT_CODE rv;
+
+       zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
+       rv = zend_parse_parameters_none();
+       zend_restore_error_handling(&zeh);
+
+       if (SUCCESS == rv) {
+               php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
+
+               if (!obj->intern) {
+                       throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
+               } else if (!obj->intern->poller) {
+                       throw_exce(EX_RUNTIME, "No asynchronous operation active");
+               } else {
+                       switch (PQflush(obj->intern->conn)) {
+                       case -1:
+                       default:
+                               throw_exce(EX_RUNTIME, "Failed to flush connection: %s", PHP_PQerrorMessage(obj->intern->conn));
+                               break;
+                       case 0:
+                               RETVAL_TRUE;
+                               break;
+                       case 1:
+                               RETVAL_FALSE;
+                               break;
+                       }
+               }
+       }
+}
+
 ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec, 0, 0, 1)
        ZEND_ARG_INFO(0, query)
 ZEND_END_ARG_INFO();
@@ -1071,7 +1153,7 @@ static PHP_METHOD(pqconn, exec) {
                        } else if (SUCCESS == php_pqres_success(res)) {
                                php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), return_value);
                        } else {
-                               php_pq_clear_res(res);
+                               php_pqres_clear(res);
                        }
 
                        php_pqconn_notify_listeners(obj);
@@ -1096,11 +1178,12 @@ static PHP_METHOD(pqconn, getResult) {
                        throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
                } else {
                        PGresult *res = PQgetResult(obj->intern->conn);
+                       php_pq_object_t *res_obj;
 
-                       if (!res) {
-                               RETVAL_NULL();
+                       if (res && (res_obj = PQresultInstanceData(res, php_pqconn_event))) {
+                               php_pq_object_to_zval_no_addref(res_obj, return_value);
                        } else {
-                               php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), return_value);
+                               RETVAL_NULL();
                        }
 
                        php_pqconn_notify_listeners(obj);
@@ -1114,7 +1197,7 @@ ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_async, 0, 0, 1)
 ZEND_END_ARG_INFO();
 static PHP_METHOD(pqconn, execAsync) {
        zend_error_handling zeh;
-       php_pq_callback_t resolver = {{0}};
+       php_pq_callback_t resolver = PHP_PQ_CALLBACK_INIT;
        char *query_str;
        size_t query_len;
        ZEND_RESULT_CODE rv;
@@ -1169,7 +1252,7 @@ static PHP_METHOD(pqconn, execParams) {
                        php_pq_params_t *params;
 
                        params = php_pq_params_init(&obj->intern->converters, ztypes ? Z_ARRVAL_P(ztypes) : NULL, Z_ARRVAL_P(zparams));
-                       res = PQexecParams(obj->intern->conn, query_str, params->param.count, params->type.oids, (const char *const*) params->param.strings, NULL, NULL, 0);
+                       res = php_pq_exec_params(obj->intern->conn, query_str, params->param.count, params->type.oids, (const char *const*) params->param.strings, NULL, NULL, 0);
                        php_pq_params_free(&params);
 
                        if (!res) {
@@ -1178,7 +1261,7 @@ static PHP_METHOD(pqconn, execParams) {
                                if (SUCCESS == php_pqres_success(res)) {
                                        php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), return_value);
                                } else {
-                                       php_pq_clear_res(res);
+                                       php_pqres_clear(res);
                                }
 
                                php_pqconn_notify_listeners(obj);
@@ -1195,7 +1278,7 @@ ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_exec_params_async, 0, 0, 2)
 ZEND_END_ARG_INFO();
 static PHP_METHOD(pqconn, execParamsAsync) {
        zend_error_handling zeh;
-       php_pq_callback_t resolver = {{0}};
+       php_pq_callback_t resolver = PHP_PQ_CALLBACK_INIT;
        char *query_str;
        size_t query_len;
        zval *zparams;
@@ -1251,7 +1334,7 @@ ZEND_RESULT_CODE php_pqconn_prepare(zval *object, php_pqconn_object_t *obj, cons
                throw_exce(EX_RUNTIME, "Failed to prepare statement (%s)", PHP_PQerrorMessage(obj->intern->conn));
        } else {
                rv = php_pqres_success(res);
-               php_pq_clear_res(res);
+               php_pqres_clear(res);
                php_pqconn_notify_listeners(obj);
        }
 
@@ -1364,7 +1447,7 @@ ZEND_RESULT_CODE php_pqconn_declare(zval *object, php_pqconn_object_t *obj, cons
                throw_exce(EX_RUNTIME, "Failed to declare cursor (%s)", PHP_PQerrorMessage(obj->intern->conn));
        } else {
                rv = php_pqres_success(res);
-               php_pq_clear_res(res);
+               php_pqres_clear(res);
                php_pqconn_notify_listeners(obj);
        }
 
@@ -1520,7 +1603,7 @@ ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_escape_bytea, 0, 0, 1)
 ZEND_END_ARG_INFO();
 static PHP_METHOD(pqconn, escapeBytea) {
        char *str;
-       int len;
+       size_t len;
 
        if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &len)) {
                php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
@@ -1599,7 +1682,7 @@ ZEND_RESULT_CODE php_pqconn_start_transaction(zval *zconn, php_pqconn_object_t *
                        throw_exce(EX_RUNTIME, "Failed to start transaction (%s)", PHP_PQerrorMessage(conn_obj->intern->conn));
                } else {
                        rv = php_pqres_success(res);
-                       php_pq_clear_res(res);
+                       php_pqres_clear(res);
                        php_pqconn_notify_listeners(conn_obj);
                }
 
@@ -1780,7 +1863,7 @@ static PHP_METHOD(pqconn, on) {
        zend_error_handling zeh;
        char *type_str;
        size_t type_len;
-       php_pq_callback_t cb = {{0}};
+       php_pq_callback_t cb = PHP_PQ_CALLBACK_INIT;
        ZEND_RESULT_CODE rv;
 
        zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
@@ -1841,7 +1924,7 @@ static PHP_METHOD(pqconn, setConverter) {
                        struct apply_set_converter_arg arg = {NULL};
 
                        ZVAL_NULL(&zoids);
-                       zend_call_method_with_0_params(zcnv, NULL, NULL, "converttypes", &zoids);
+                       php_pq_call_method(zcnv, "converttypes", 0, &zoids);
                        ZVAL_DUP(&tmp, &zoids);
                        convert_to_array(&tmp);
 
@@ -1879,7 +1962,7 @@ static PHP_METHOD(pqconn, unsetConverter) {
                        struct apply_set_converter_arg arg = {NULL};
 
                        ZVAL_NULL(&zoids);
-                       zend_call_method_with_0_params(zcnv, NULL, NULL, "converttypes", &zoids);
+                       php_pq_call_method(zcnv, "converttypes", 0, &zoids);
                        ZVAL_DUP(&tmp, &zoids);
                        convert_to_array(&tmp);
 
@@ -1896,10 +1979,11 @@ static PHP_METHOD(pqconn, unsetConverter) {
 }
 
 static zend_function_entry php_pqconn_methods[] = {
-       PHP_ME(pqconn, __construct, ai_pqconn_construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
+       PHP_ME(pqconn, __construct, ai_pqconn_construct, ZEND_ACC_PUBLIC)
        PHP_ME(pqconn, reset, ai_pqconn_reset, ZEND_ACC_PUBLIC)
        PHP_ME(pqconn, resetAsync, ai_pqconn_reset_async, ZEND_ACC_PUBLIC)
        PHP_ME(pqconn, poll, ai_pqconn_poll, ZEND_ACC_PUBLIC)
+       PHP_ME(pqconn, flush, ai_pqconn_flush, ZEND_ACC_PUBLIC)
        PHP_ME(pqconn, exec, ai_pqconn_exec, ZEND_ACC_PUBLIC)
        PHP_ME(pqconn, execAsync, ai_pqconn_exec_async, ZEND_ACC_PUBLIC)
        PHP_ME(pqconn, execParams, ai_pqconn_exec_params, ZEND_ACC_PUBLIC)
@@ -1952,12 +2036,12 @@ PHP_MINIT_FUNCTION(pqconn)
        php_pqconn_object_handlers.read_property = php_pq_object_read_prop;
        php_pqconn_object_handlers.write_property = php_pq_object_write_prop;
        php_pqconn_object_handlers.clone_obj = NULL;
-       php_pqconn_object_handlers.get_property_ptr_ptr = NULL;
+       php_pqconn_object_handlers.get_property_ptr_ptr = php_pq_object_get_prop_ptr_null;
        php_pqconn_object_handlers.get_gc = php_pq_object_get_gc;
        php_pqconn_object_handlers.get_properties = php_pq_object_properties;
        php_pqconn_object_handlers.get_debug_info = php_pq_object_debug_info;
 
-       zend_hash_init(&php_pqconn_object_prophandlers, 22, NULL, php_pq_object_prophandler_dtor, 1);
+       zend_hash_init(&php_pqconn_object_prophandlers, 23, NULL, php_pq_object_prophandler_dtor, 1);
 
        zend_declare_property_long(php_pqconn_class_entry, ZEND_STRL("status"), CONNECTION_BAD, ZEND_ACC_PUBLIC);
        ph.read = php_pqconn_object_read_status;
@@ -1991,6 +2075,12 @@ PHP_MINIT_FUNCTION(pqconn)
        zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "unbuffered", sizeof("unbuffered")-1, (void *) &ph, sizeof(ph));
        ph.write = NULL;
 
+       zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("nonblocking"), 0, ZEND_ACC_PUBLIC);
+       ph.read = php_pqconn_object_read_nonblocking;
+       ph.write = php_pqconn_object_write_nonblocking;
+       zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "nonblocking", sizeof("nonblocking")-1, (void *) &ph, sizeof(ph));
+       ph.write = NULL;
+
        zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("db"), ZEND_ACC_PUBLIC);
        ph.read = php_pqconn_object_read_db;
        zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "db", sizeof("db")-1, (void *) &ph, sizeof(ph));
@@ -2069,6 +2159,24 @@ PHP_MINIT_FUNCTION(pqconn)
        zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "defaultAutoConvert", sizeof("defaultAutoConvert")-1, (void *) &ph, sizeof(ph));
        ph.write = NULL;
 
+#ifdef HAVE_PQLIBVERSION
+       zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("libraryVersion"), ZEND_ACC_PUBLIC|ZEND_ACC_READONLY);
+       ph.read = php_pqconn_object_read_lib_version;
+       zend_hash_str_add_mem(&php_pqconn_object_prophandlers, ZEND_STRL("libraryVersion"), (void *) &ph, sizeof(ph));
+#endif
+
+#ifdef HAVE_PQPROTOCOLVERSION
+       zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("protocolVersion"), ZEND_ACC_PUBLIC|ZEND_ACC_READONLY);
+       ph.read = php_pqconn_object_read_protocol_version;
+       zend_hash_str_add_mem(&php_pqconn_object_prophandlers, ZEND_STRL("protocolVersion"), (void *) &ph, sizeof(ph));
+#endif
+
+#ifdef HAVE_PQSERVERVERSION
+       zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("serverVersion"), ZEND_ACC_PUBLIC|ZEND_ACC_READONLY);
+       ph.read = php_pqconn_object_read_server_version;
+       zend_hash_str_add_mem(&php_pqconn_object_prophandlers, ZEND_STRL("serverVersion"), (void *) &ph, sizeof(ph));
+#endif
+
        zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("OK"), CONNECTION_OK);
        zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("BAD"), CONNECTION_BAD);
        zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("STARTED"), CONNECTION_STARTED);
@@ -2077,6 +2185,15 @@ PHP_MINIT_FUNCTION(pqconn)
        zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("AUTH_OK"), CONNECTION_AUTH_OK);
        zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("SSL_STARTUP"), CONNECTION_SSL_STARTUP);
        zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("SETENV"), CONNECTION_SETENV);
+#ifdef HAVE_CONNECTION_CHECK_WRITABLE
+       zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("CHECK_WRITABLE"), CONNECTION_CHECK_WRITABLE);
+#endif
+#ifdef HAVE_CONNECTION_CONSUME
+       zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("CONSUME"), CONNECTION_CONSUME);
+#endif
+#ifdef HAVE_CONNECTION_GSS_STARTUP
+       zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("GSS_STARTUP"), CONNECTION_GSS_STARTUP);
+#endif
 
        zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_IDLE"), PQTRANS_IDLE);
        zend_declare_class_constant_long(php_pqconn_class_entry, ZEND_STRL("TRANS_ACTIVE"), PQTRANS_ACTIVE);