fix master compatibility
[m6w6/ext-pq] / src / php_pqconn.c
index a7fca0ed7014ebd9e3db40951ad13892fb5eb8a9..9b507b62591d381d042e1a0b082a67d9b80cb676 100644 (file)
@@ -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);
@@ -215,6 +216,20 @@ static void php_pqconn_object_write_unbuffered(zval *object, void *o, zval *valu
        obj->intern->unbuffered = z_is_true(value);
 }
 
+static void php_pqconn_object_read_nonblocking(zval *object, void *o, zval *return_value)
+{
+       php_pqconn_object_t *obj = o;
+
+       RETVAL_BOOL(PQisnonblocking(obj->intern->conn));
+}
+
+static void php_pqconn_object_write_nonblocking(zval *object, 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(zval *object, void *o, zval *return_value)
 {
        php_pqconn_object_t *obj = o;
@@ -552,7 +567,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_PQclear(res);
+       php_pqres_clear(res);
 
        if (CONNECTION_OK != PQstatus(*handle)) {
                PQreset(*handle);
@@ -586,7 +601,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_PQclear(res);
+               php_pqres_clear(res);
        }
 
        return ZEND_HASH_APPLY_REMOVE;
@@ -613,7 +628,7 @@ static void php_pqconn_retire(php_persistent_handle_factory_t *f, void **handle)
        }
        /* clean up async results */
        while ((res = PQgetResult(*handle))) {
-               PHP_PQclear(res);
+               php_pqres_clear(res);
        }
 
        /* clean up transaction & session */
@@ -627,7 +642,7 @@ static void php_pqconn_retire(php_persistent_handle_factory_t *f, void **handle)
        }
 
        if (res) {
-               PHP_PQclear(res);
+               php_pqres_clear(res);
        }
 
        if (evdata) {
@@ -652,7 +667,7 @@ static PHP_METHOD(pqconn, __construct) {
 
        zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh);
        rv = zend_parse_parameters(ZEND_NUM_ARGS(), "|sl", &dsn_str, &dsn_len, &flags);
-       zend_restore_error_handling(&zeh TSRMLS_CC);
+       zend_restore_error_handling(&zeh);
 
        if (SUCCESS == rv) {
                php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
@@ -668,6 +683,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);
 
@@ -737,10 +753,10 @@ static PHP_METHOD(pqconn, resetAsync) {
                php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
 
                if (!obj->intern) {
-                       throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
+                       throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
                } else {
                        if (!PQresetStart(obj->intern->conn)) {
-                               throw_exce(EX_IO TSRMLS_CC, "Failed to start connection reset (%s)", PHP_PQerrorMessage(obj->intern->conn));
+                               throw_exce(EX_IO, "Failed to start connection reset (%s)", PHP_PQerrorMessage(obj->intern->conn));
                        } else {
                                obj->intern->poller = (int (*)(PGconn*)) PQresetPoll;
                        }
@@ -774,7 +790,7 @@ static PHP_METHOD(pqconn, unlisten)
 
                        if (res) {
                                php_pqres_success(res);
-                               PHP_PQclear(res);
+                               php_pqres_clear(res);
                        }
                }
        }
@@ -879,7 +895,7 @@ static PHP_METHOD(pqconn, listen) {
                                smart_str_appends(&cmd, quoted_channel);
                                smart_str_0(&cmd);
 
-                               res = PQexec(obj->intern->conn, smart_str_v(&cmd));
+                               res = php_pq_exec(obj->intern->conn, smart_str_v(&cmd));
 
                                smart_str_free(&cmd);
                                PQfreemem(quoted_channel);
@@ -891,7 +907,7 @@ static PHP_METHOD(pqconn, listen) {
                                                obj->intern->poller = PQconsumeInput;
                                                php_pqconn_add_listener(obj, channel_str, channel_len, &listener);
                                        }
-                                       PHP_PQclear(res);
+                                       php_pqres_clear(res);
                                }
 
                                php_pqconn_notify_listeners(obj);
@@ -919,12 +935,12 @@ static PHP_METHOD(pqconn, listenAsync) {
                php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
 
                if (!obj->intern) {
-                       throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
+                       throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
                } else {
                        char *quoted_channel = PQescapeIdentifier(obj->intern->conn, channel_str, channel_len);
 
                        if (!quoted_channel) {
-                               throw_exce(EX_ESCAPE TSRMLS_CC, "Failed to escape channel identifier (%s)", PHP_PQerrorMessage(obj->intern->conn));
+                               throw_exce(EX_ESCAPE, "Failed to escape channel identifier (%s)", PHP_PQerrorMessage(obj->intern->conn));
                        } else {
                                smart_str cmd = {0};
 
@@ -976,7 +992,7 @@ static PHP_METHOD(pqconn, notify) {
                                throw_exce(EX_RUNTIME, "Failed to notify listeners (%s)", PHP_PQerrorMessage(obj->intern->conn));
                        } else {
                                php_pqres_success(res);
-                               PHP_PQclear(res);
+                               php_pqres_clear(res);
                        }
 
                        php_pqconn_notify_listeners(obj);
@@ -1045,6 +1061,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();
@@ -1064,14 +1114,14 @@ static PHP_METHOD(pqconn, exec) {
                if (!obj->intern) {
                        throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
                } else {
-                       PGresult *res = PQexec(obj->intern->conn, query_str);
+                       PGresult *res = php_pq_exec(obj->intern->conn, query_str);
 
                        if (!res) {
                                throw_exce(EX_RUNTIME, "Failed to execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
                        } else if (SUCCESS == php_pqres_success(res)) {
                                php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), return_value);
                        } else {
-                               PHP_PQclear(res);
+                               php_pqres_clear(res);
                        }
 
                        php_pqconn_notify_listeners(obj);
@@ -1096,11 +1146,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);
@@ -1178,7 +1229,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_PQclear(res);
+                                       php_pqres_clear(res);
                                }
 
                                php_pqconn_notify_listeners(obj);
@@ -1244,14 +1295,14 @@ ZEND_RESULT_CODE php_pqconn_prepare(zval *object, php_pqconn_object_t *obj, cons
                obj = PHP_PQ_OBJ(object, NULL);
        }
 
-       res = PQprepare(obj->intern->conn, name, query, params->type.count, params->type.oids);
+       res = php_pq_prepare(obj->intern->conn, name, query, params->type.count, params->type.oids);
 
        if (!res) {
                rv = FAILURE;
                throw_exce(EX_RUNTIME, "Failed to prepare statement (%s)", PHP_PQerrorMessage(obj->intern->conn));
        } else {
                rv = php_pqres_success(res);
-               PHP_PQclear(res);
+               php_pqres_clear(res);
                php_pqconn_notify_listeners(obj);
        }
 
@@ -1293,7 +1344,7 @@ static PHP_METHOD(pqconn, prepare) {
        }
 }
 
-ZEND_RESULT_CODE php_pqconn_prepare_async(zval *object, php_pqconn_object_t *obj, const char *name, const char *query, php_pq_params_t *params TSRMLS_DC)
+ZEND_RESULT_CODE php_pqconn_prepare_async(zval *object, php_pqconn_object_t *obj, const char *name, const char *query, php_pq_params_t *params)
 {
        ZEND_RESULT_CODE rv;
 
@@ -1357,14 +1408,14 @@ ZEND_RESULT_CODE php_pqconn_declare(zval *object, php_pqconn_object_t *obj, cons
                obj = PHP_PQ_OBJ(object, NULL);
        }
 
-       res = PQexec(obj->intern->conn, decl);
+       res = php_pq_exec(obj->intern->conn, decl);
 
        if (!res) {
                rv = FAILURE;
                throw_exce(EX_RUNTIME, "Failed to declare cursor (%s)", PHP_PQerrorMessage(obj->intern->conn));
        } else {
                rv = php_pqres_success(res);
-               PHP_PQclear(res);
+               php_pqres_clear(res);
                php_pqconn_notify_listeners(obj);
        }
 
@@ -1520,7 +1571,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);
@@ -1578,7 +1629,7 @@ ZEND_RESULT_CODE php_pqconn_start_transaction(zval *zconn, php_pqconn_object_t *
        }
 
        if (!conn_obj->intern) {
-               throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
+               throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
        } else {
                PGresult *res;
                smart_str cmd = {0};
@@ -1593,13 +1644,13 @@ ZEND_RESULT_CODE php_pqconn_start_transaction(zval *zconn, php_pqconn_object_t *
                smart_str_appends(&cmd, " DEFERRABLE");
                smart_str_0(&cmd);
 
-               res = PQexec(conn_obj->intern->conn, smart_str_v(&cmd));
+               res = php_pq_exec(conn_obj->intern->conn, smart_str_v(&cmd));
 
                if (!res) {
                        throw_exce(EX_RUNTIME, "Failed to start transaction (%s)", PHP_PQerrorMessage(conn_obj->intern->conn));
                } else {
                        rv = php_pqres_success(res);
-                       PHP_PQclear(res);
+                       php_pqres_clear(res);
                        php_pqconn_notify_listeners(conn_obj);
                }
 
@@ -1791,7 +1842,7 @@ static PHP_METHOD(pqconn, on) {
                php_pqconn_object_t *obj = PHP_PQ_OBJ(getThis(), NULL);
 
                if (!obj->intern) {
-                       throw_exce(EX_UNINITIALIZED TSRMLS_CC, "pq\\Connection not initialized");
+                       throw_exce(EX_UNINITIALIZED, "pq\\Connection not initialized");
                } else {
                        RETVAL_LONG(php_pqconn_add_eventhandler(obj, type_str, type_len, &cb));
                }
@@ -1896,10 +1947,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)
@@ -1957,7 +2009,7 @@ PHP_MINIT_FUNCTION(pqconn)
        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 +2043,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));
@@ -2057,7 +2115,7 @@ PHP_MINIT_FUNCTION(pqconn)
        zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "defaultTransactionReadonly", sizeof("defaultTransactionReadonly")-1, (void *) &ph, sizeof(ph));
        ph.write = NULL;
 
-       zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("defaultTransactionDeferrable"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
+       zend_declare_property_bool(php_pqconn_class_entry, ZEND_STRL("defaultTransactionDeferrable"), 0, ZEND_ACC_PUBLIC);
        ph.read = php_pqconn_object_read_def_txn_deferrable;
        ph.write = php_pqconn_object_write_def_txn_deferrable;
        zend_hash_str_add_mem(&php_pqconn_object_prophandlers, "defaultTransactionDeferrable", sizeof("defaultTransactionDeferrable")-1, (void *) &ph, sizeof(ph));