X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-pq;a=blobdiff_plain;f=src%2Fphp_pqconn.c;h=d0ddfef9317c8036cc666f835dea8197c82bee63;hp=a7fca0ed7014ebd9e3db40951ad13892fb5eb8a9;hb=65b81572a092cc9aa9b980f30f7793b45803a211;hpb=1e2615005272bb2347820bccb38c94b9caccafb8 diff --git a/src/php_pqconn.c b/src/php_pqconn.c index a7fca0e..d0ddfef 100644 --- a/src/php_pqconn.c +++ b/src/php_pqconn.c @@ -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); } @@ -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)); } @@ -1900,6 +1951,7 @@ static zend_function_entry php_pqconn_methods[] = { 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));