diff --git a/src/php_pq_callback.c b/src/php_pq_callback.c index 695d592..17d7e70 100644 --- a/src/php_pq_callback.c +++ b/src/php_pq_callback.c @@ -84,36 +84,79 @@ zval *php_pq_callback_to_zval_no_addref(php_pq_callback_t *cb, zval *tmp) zend_bool php_pq_callback_is_locked(php_pq_callback_t *cb) { /* TODO: fixed in php7? - if (cb->fci.size > 0 && Z_TYPE_P(cb->fci.function_name) == IS_OBJECT) { - const zend_function *closure = zend_get_closure_method_def(cb->fci.function_name); + if (php_pq_callback_is_enabled(cb)) { + const zend_function *closure; + const zend_execute_data *ex; - if (closure->type == ZEND_USER_FUNCTION) { - zend_execute_data *ex = EG(current_execute_data); + if (Z_TYPE_P(cb->fci.function_name) != IS_OBJECT) { + return 0; + } - while (ex) { - if (ex->op_array == &closure->op_array) { - return 1; - } - ex = ex->prev_execute_data; + closure = zend_get_closure_method_def(cb->fci.function_name); + if (closure->type != ZEND_USER_FUNCTION) { + return 0; + } + + for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) { + if (ex->op_array == &closure->op_array) { + return 1; } } } + if (!php_pq_callback_is_recurrent(cb)) { + return 0; + } + return php_pq_callback_is_locked(cb->recursion); */ return 0; } -void php_pq_callback_recurse(php_pq_callback_t *old, php_pq_callback_t *new TSRMLS_DC) +void php_pq_callback_recurse(php_pq_callback_t *old, php_pq_callback_t *new) { - if (new && new->fci.size > 0 && php_pq_callback_is_locked(old TSRMLS_CC)) { - new->recursion = emalloc(sizeof(*old)); - memcpy(new->recursion, old, sizeof(*old)); - } else if (new && new->fci.size > 0) { - php_pq_callback_dtor(old); - php_pq_callback_addref(new); - memcpy(old, new, sizeof(*old)); - new->fci.size = 0; + if (php_pq_callback_is_locked(old)) { + php_pq_callback_recurse_ex(old, new); } else { php_pq_callback_dtor(old); + if (php_pq_callback_is_enabled(new)) { + php_pq_callback_addref(new); + memcpy(old, new, sizeof(*old)); + new->fci.size = 0; + } + } +} + +extern zend_bool php_pq_callback_is_enabled(php_pq_callback_t *cb) +{ + return cb && cb->fci.size > 0; +} + +extern zend_bool php_pq_callback_is_recurrent(php_pq_callback_t *cb) +{ + return cb && cb->recursion != NULL; +} + +extern void php_pq_callback_disable(php_pq_callback_t *cb) +{ + if (php_pq_callback_is_enabled(cb)) { + php_pq_callback_recurse_ex(cb, NULL); + } +} + +extern void php_pq_callback_recurse_ex(php_pq_callback_t *old, php_pq_callback_t *new) +{ + php_pq_callback_t *tmp = emalloc(sizeof(*tmp)); + + if (new) { + memcpy(tmp, old, sizeof(*tmp)); + memcpy(old, new, sizeof(*old)); + old->recursion = tmp; + + php_pq_callback_addref(old); + php_pq_callback_disable(tmp); + } else { + memcpy(tmp, old, sizeof(*tmp)); + memset(old, 0, sizeof(*old)); + old->recursion = tmp; } } diff --git a/src/php_pq_callback.h b/src/php_pq_callback.h index da71143..efcbd96 100644 --- a/src/php_pq_callback.h +++ b/src/php_pq_callback.h @@ -27,6 +27,10 @@ extern zval *php_pq_callback_to_zval(php_pq_callback_t *cb, zval *tmp); extern zval *php_pq_callback_to_zval_no_addref(php_pq_callback_t *cb, zval *tmp); extern zend_bool php_pq_callback_is_locked(php_pq_callback_t *cb); extern void php_pq_callback_recurse(php_pq_callback_t *old, php_pq_callback_t *new); +extern zend_bool php_pq_callback_is_enabled(php_pq_callback_t *cb); +extern void php_pq_callback_disable(php_pq_callback_t *cb); +extern void php_pq_callback_recurse_ex(php_pq_callback_t *old, php_pq_callback_t *new); +extern zend_bool php_pq_callback_is_recurrent(php_pq_callback_t *cb); #endif diff --git a/src/php_pq_misc.c b/src/php_pq_misc.c index 10defed..9eccae9 100644 --- a/src/php_pq_misc.c +++ b/src/php_pq_misc.c @@ -24,10 +24,61 @@ #include "php_pq.h" #include "php_pqexc.h" +#include "php_pqconn_event.h" #include "php_pq_misc.h" #undef PHP_PQ_TYPE #include "php_pq_type.h" + +/* clear result object associated with a result handle */ +void php_pq_clear_res(PGresult *r) { + php_pq_object_t *o = PQresultInstanceData(r, php_pqconn_event); + + if (o) { + php_pq_object_delref(o); + } else { + PQclear(r); + } +} + +/* clear any asynchronous results */ +void php_pq_clear_conn(PGconn *conn) { + PGresult *r; + php_pqconn_event_data_t *evdata = PQinstanceData(conn, php_pqconn_event); + + while ((r = PQgetResult(conn))) { + php_pq_clear_res(r); + } + + if (evdata && evdata->obj) { + if (php_pq_callback_is_enabled(&evdata->obj->intern->onevent)) { + if (php_pq_callback_is_locked(&evdata->obj->intern->onevent)) { + php_pq_callback_disable(&evdata->obj->intern->onevent); + } else { + php_pq_callback_dtor(&evdata->obj->intern->onevent); + } + } + } +} + +/* safe wrappers to clear any asynchronous wrappers before querying synchronously */ +PGresult *php_pq_exec(PGconn *conn, const char *query) { + php_pq_clear_conn(conn); + return PQexec(conn, query); +} +PGresult *php_pq_exec_params(PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char *const * paramValues, const int *paramLengths, const int *paramFormats, int resultFormat) { + php_pq_clear_conn(conn); + return PQexecParams(conn, command, nParams, paramTypes, paramValues, paramLengths, paramFormats, resultFormat); +} +PGresult *php_pq_prepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes) { + php_pq_clear_conn(conn); + return PQprepare(conn, stmtName, query, nParams, paramTypes); +} +PGresult *php_pq_exec_prepared(PGconn *conn, const char *stmtName, int nParams, const char *const * paramValues, const int *paramLengths, const int *paramFormats, int resultFormat) { + php_pq_clear_conn(conn); + return PQexecPrepared(conn, stmtName, nParams, paramValues, paramLengths, paramFormats, resultFormat); +} + char *php_pq_rtrim(char *e) { size_t l = strlen(e); @@ -370,7 +421,7 @@ static ZEND_RESULT_CODE parse_array(ArrayParserState *a) return SUCCESS; } -HashTable *php_pq_parse_array(php_pqres_t *res, const char *val_str, size_t val_len, Oid typ TSRMLS_DC) +HashTable *php_pq_parse_array(php_pqres_t *res, const char *val_str, size_t val_len, Oid typ) { HashTable *ht = NULL; ArrayParserState a = {0}; diff --git a/src/php_pq_misc.h b/src/php_pq_misc.h index b25f871..26ac0e1 100644 --- a/src/php_pq_misc.h +++ b/src/php_pq_misc.h @@ -16,15 +16,6 @@ #include -#if PHP_VERSION_ID < 50500 -#undef SUCCESS -#undef FAILURE -typedef enum { - SUCCESS = 0, - FAILURE = -1 -} ZEND_RESULT_CODE; -#endif - #include "php_pqres.h" #define z_is_true zend_is_true @@ -32,6 +23,17 @@ typedef enum { #define smart_str_v(ss) (ss)->s->val #define smart_str_l(ss) (ss)->s->len +/* clear result object associated with a result handle */ +extern void php_pq_clear_res(PGresult *r); +/* clear any asynchronous results */ +extern void php_pq_clear_conn(PGconn *conn); +/* safe wrappers to clear any asynchronous wrappers before querying synchronously */ +extern PGresult *php_pq_exec(PGconn *conn, const char *query); +extern PGresult *php_pq_exec_params(PGconn *conn, const char *command, int nParams, const Oid *paramTypes, const char *const * paramValues, const int *paramLengths, const int *paramFormats, int resultFormat); +extern PGresult *php_pq_prepare(PGconn *conn, const char *stmtName, const char *query, int nParams, const Oid *paramTypes); +extern PGresult *php_pq_exec_prepared(PGconn *conn, const char *stmtName, int nParams, const char *const * paramValues, const int *paramLengths, const int *paramFormats, int resultFormat); + + /* trim LF from EOL */ extern char *php_pq_rtrim(char *e); diff --git a/src/php_pq_module.c b/src/php_pq_module.c index 53ec94c..cd99217 100644 --- a/src/php_pq_module.c +++ b/src/php_pq_module.c @@ -18,7 +18,7 @@ #include #include -#include +#include #include "php_pq.h" #include "php_pq_misc.h" diff --git a/src/php_pqcancel.c b/src/php_pqcancel.c index 4d5d339..400e007 100644 --- a/src/php_pqcancel.c +++ b/src/php_pqcancel.c @@ -49,7 +49,7 @@ php_pqcancel_object_t *php_pqcancel_create_object_ex(zend_class_entry *ce, php_p &php_pqcancel_object_handlers, &php_pqcancel_object_prophandlers); } -static zend_object *php_pqcancel_create_object(zend_class_entry *class_type TSRMLS_DC) +static zend_object *php_pqcancel_create_object(zend_class_entry *class_type) { return &php_pqcancel_create_object_ex(class_type, NULL)->zo; } diff --git a/src/php_pqconn.c b/src/php_pqconn.c index a7fca0e..07c907f 100644 --- a/src/php_pqconn.c +++ b/src/php_pqconn.c @@ -552,7 +552,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_pq_clear_res(res); if (CONNECTION_OK != PQstatus(*handle)) { PQreset(*handle); @@ -586,7 +586,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_pq_clear_res(res); } return ZEND_HASH_APPLY_REMOVE; @@ -613,7 +613,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_pq_clear_res(res); } /* clean up transaction & session */ @@ -627,7 +627,7 @@ static void php_pqconn_retire(php_persistent_handle_factory_t *f, void **handle) } if (res) { - PHP_PQclear(res); + php_pq_clear_res(res); } if (evdata) { @@ -652,7 +652,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); @@ -737,10 +737,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 +774,7 @@ static PHP_METHOD(pqconn, unlisten) if (res) { php_pqres_success(res); - PHP_PQclear(res); + php_pq_clear_res(res); } } } @@ -879,7 +879,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 +891,7 @@ static PHP_METHOD(pqconn, listen) { obj->intern->poller = PQconsumeInput; php_pqconn_add_listener(obj, channel_str, channel_len, &listener); } - PHP_PQclear(res); + php_pq_clear_res(res); } php_pqconn_notify_listeners(obj); @@ -919,12 +919,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 +976,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_pq_clear_res(res); } php_pqconn_notify_listeners(obj); @@ -1064,14 +1064,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_pq_clear_res(res); } php_pqconn_notify_listeners(obj); @@ -1178,7 +1178,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_pq_clear_res(res); } php_pqconn_notify_listeners(obj); @@ -1244,14 +1244,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_pq_clear_res(res); php_pqconn_notify_listeners(obj); } @@ -1293,7 +1293,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 +1357,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_pq_clear_res(res); php_pqconn_notify_listeners(obj); } @@ -1578,7 +1578,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 +1593,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_pq_clear_res(res); php_pqconn_notify_listeners(conn_obj); } @@ -1791,7 +1791,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)); } @@ -2057,7 +2057,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)); diff --git a/src/php_pqconn.h b/src/php_pqconn.h index 65c1278..3a26a5a 100644 --- a/src/php_pqconn.h +++ b/src/php_pqconn.h @@ -20,6 +20,7 @@ #include #include "php_pq_object.h" #include "php_pq_callback.h" +#include "php_pq_object.h" #include "php_pq_params.h" typedef struct php_pqconn { diff --git a/src/php_pqconn_event.c b/src/php_pqconn_event.c index 2b94dee..8cdb761 100644 --- a/src/php_pqconn_event.c +++ b/src/php_pqconn_event.c @@ -80,7 +80,7 @@ static void php_pqconn_event_resultcreate(PGEventResultCreate *event) } /* async callback */ - if (data->obj->intern->onevent.fci.size > 0) { + if (php_pq_callback_is_enabled(&data->obj->intern->onevent)) { zval res; php_pq_object_to_zval(obj, &res); diff --git a/src/php_pqcopy.c b/src/php_pqcopy.c index 2413268..1a6d37e 100644 --- a/src/php_pqcopy.c +++ b/src/php_pqcopy.c @@ -141,7 +141,7 @@ static PHP_METHOD(pqcopy, __construct) { smart_str_appendl(&cmd, opt_str, opt_len); 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 %s (%s)", smart_str_v(&cmd), PHP_PQerrorMessage(obj->intern->conn->intern->conn)); @@ -155,7 +155,7 @@ static PHP_METHOD(pqcopy, __construct) { php_pq_object_addref(conn_obj); } - PHP_PQclear(res); + php_pq_clear_res(res); } smart_str_free(&cmd); @@ -223,7 +223,7 @@ static PHP_METHOD(pqcopy, end) { throw_exce(EX_RUNTIME, "Failed to fetch COPY result (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { php_pqres_success(res); - PHP_PQclear(res); + php_pq_clear_res(res); } } @@ -241,7 +241,7 @@ static PHP_METHOD(pqcopy, get) { ZEND_RESULT_CODE rv; zend_replace_error_handling(EH_THROW, exce(EX_INVALID_ARGUMENT), &zeh); - rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zdata); + rv = zend_parse_parameters(ZEND_NUM_ARGS(), "z", &zdata); zend_restore_error_handling(&zeh); if (SUCCESS == rv) { @@ -268,7 +268,7 @@ static PHP_METHOD(pqcopy, get) { throw_exce(EX_RUNTIME, "Failed to fetch COPY result (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { php_pqres_success(res); - PHP_PQclear(res); + php_pq_clear_res(res); RETVAL_FALSE; } break; diff --git a/src/php_pqcur.c b/src/php_pqcur.c index 7a96994..4197cdf 100644 --- a/src/php_pqcur.c +++ b/src/php_pqcur.c @@ -47,8 +47,8 @@ static void cur_close(php_pqcur_object_t *obj, zend_bool async, zend_bool silent throw_exce(EX_IO, "Failed to close cursor (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } } else { - if ((res = PQexec(obj->intern->conn->intern->conn, smart_str_v(&cmd)))) { - PHP_PQclear(res); + if ((res = php_pq_exec(obj->intern->conn->intern->conn, smart_str_v(&cmd)))) { + php_pq_clear_res(res); } else if (!silent) { throw_exce(EX_RUNTIME, "Failed to close cursor (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } @@ -133,7 +133,7 @@ static void cur_fetch_or_move(INTERNAL_FUNCTION_PARAMETERS, const char *action, obj->intern->conn->intern->poller = PQconsumeInput; } } else { - PGresult *res = PQexec(obj->intern->conn->intern->conn, smart_str_v(&cmd)); + PGresult *res = php_pq_exec(obj->intern->conn->intern->conn, smart_str_v(&cmd)); if (!res) { throw_exce(EX_RUNTIME, "Failed to %s cursor (%s)", *action == 'f' ? "fetch from" : "move in", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); @@ -460,7 +460,7 @@ PHP_MINIT_FUNCTION(pqcur) ph.read = php_pqcur_object_read_query; zend_hash_str_add_mem(&php_pqcur_object_prophandlers, "query", sizeof("query")-1, (void *) &ph, sizeof(ph)); - zend_declare_property_null(php_pqcur_class_entry, ZEND_STRL("flags"), ZEND_ACC_PUBLIC TSRMLS_CC); + zend_declare_property_null(php_pqcur_class_entry, ZEND_STRL("flags"), ZEND_ACC_PUBLIC); ph.read = php_pqcur_object_read_flags; zend_hash_str_add_mem(&php_pqcur_object_prophandlers, "flags", sizeof("flags")-1, (void *) &ph, sizeof(ph)); diff --git a/src/php_pqlob.c b/src/php_pqlob.c index 01c0ec2..b5cbf5c 100644 --- a/src/php_pqlob.c +++ b/src/php_pqlob.c @@ -100,7 +100,7 @@ static void php_pqlob_object_read_stream(zval *object, void *o, zval *return_val RETVAL_ZVAL(&zstream, 1, 0); } -static size_t php_pqlob_stream_write(php_stream *stream, const char *buffer, size_t length TSRMLS_DC) +static size_t php_pqlob_stream_write(php_stream *stream, const char *buffer, size_t length) { php_pqlob_object_t *obj = stream->abstract; int written = 0; @@ -109,16 +109,16 @@ static size_t php_pqlob_stream_write(php_stream *stream, const char *buffer, siz written = lo_write(obj->intern->txn->intern->conn->intern->conn, obj->intern->lofd, buffer, length); if (written < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write to LOB with oid=%u (%s)", obj->intern->loid, PHP_PQerrorMessage(obj->intern->txn->intern->conn->intern->conn)); + php_error_docref(NULL, E_WARNING, "Failed to write to LOB with oid=%u (%s)", obj->intern->loid, PHP_PQerrorMessage(obj->intern->txn->intern->conn->intern->conn)); } - php_pqconn_notify_listeners(obj->intern->txn->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->txn->intern->conn); } return written; } -static size_t php_pqlob_stream_read(php_stream *stream, char *buffer, size_t length TSRMLS_DC) +static size_t php_pqlob_stream_read(php_stream *stream, char *buffer, size_t length) { php_pqlob_object_t *obj = stream->abstract; int read = 0; @@ -133,27 +133,27 @@ static size_t php_pqlob_stream_read(php_stream *stream, char *buffer, size_t len read = lo_read(obj->intern->txn->intern->conn->intern->conn, obj->intern->lofd, buffer, length); if (read < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to read from LOB with oid=%d (%s)", obj->intern->loid, PHP_PQerrorMessage(obj->intern->txn->intern->conn->intern->conn)); + php_error_docref(NULL, E_WARNING, "Failed to read from LOB with oid=%d (%s)", obj->intern->loid, PHP_PQerrorMessage(obj->intern->txn->intern->conn->intern->conn)); } } - php_pqconn_notify_listeners(obj->intern->txn->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->txn->intern->conn); } return read; } -static ZEND_RESULT_CODE php_pqlob_stream_close(php_stream *stream, int close_handle TSRMLS_DC) +static ZEND_RESULT_CODE php_pqlob_stream_close(php_stream *stream, int close_handle) { return SUCCESS; } -static int php_pqlob_stream_flush(php_stream *stream TSRMLS_DC) +static int php_pqlob_stream_flush(php_stream *stream) { return SUCCESS; } -static ZEND_RESULT_CODE php_pqlob_stream_seek(php_stream *stream, off_t offset, int whence, off_t *newoffset TSRMLS_DC) +static ZEND_RESULT_CODE php_pqlob_stream_seek(php_stream *stream, off_t offset, int whence, off_t *newoffset) { ZEND_RESULT_CODE rv = FAILURE; php_pqlob_object_t *obj = stream->abstract; @@ -162,14 +162,14 @@ static ZEND_RESULT_CODE php_pqlob_stream_seek(php_stream *stream, off_t offset, int position = lo_lseek(obj->intern->txn->intern->conn->intern->conn, obj->intern->lofd, offset, whence); if (position < 0) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to seek offset in LOB with oid=%d (%s)", obj->intern->loid, PHP_PQerrorMessage(obj->intern->txn->intern->conn->intern->conn)); + php_error_docref(NULL, E_WARNING, "Failed to seek offset in LOB with oid=%d (%s)", obj->intern->loid, PHP_PQerrorMessage(obj->intern->txn->intern->conn->intern->conn)); rv = FAILURE; } else { *newoffset = position; rv = SUCCESS; } - php_pqconn_notify_listeners(obj->intern->txn->intern->conn TSRMLS_CC); + php_pqconn_notify_listeners(obj->intern->txn->intern->conn); } return rv; diff --git a/src/php_pqres.c b/src/php_pqres.c index 68645a1..1bc0d1d 100644 --- a/src/php_pqres.c +++ b/src/php_pqres.c @@ -374,7 +374,7 @@ static ZEND_RESULT_CODE php_pqres_count_elements(zval *object, long *count) } } -ZEND_RESULT_CODE php_pqres_success(PGresult *res TSRMLS_DC) +ZEND_RESULT_CODE php_pqres_success(PGresult *res) { zval zexc; @@ -529,7 +529,7 @@ static void php_pqres_object_write_auto_conv(zval *object, void *o, zval *value) obj->intern->auto_convert = zval_get_long(value); } -static ZEND_RESULT_CODE php_pqres_iteration(zval *zobj, php_pqres_object_t *obj, php_pqres_fetch_t fetch_type, zval *row TSRMLS_DC) +static ZEND_RESULT_CODE php_pqres_iteration(zval *zobj, php_pqres_object_t *obj, php_pqres_fetch_t fetch_type, zval *row) { ZEND_RESULT_CODE rv; php_pqres_fetch_t orig_fetch; diff --git a/src/php_pqres.h b/src/php_pqres.h index acc03cc..cc20ddb 100644 --- a/src/php_pqres.h +++ b/src/php_pqres.h @@ -59,14 +59,6 @@ extern php_pqres_fetch_t php_pqres_fetch_type(php_pqres_t *res); #include "php_pq_object.h" #include "php_pqconn_event.h" -#define PHP_PQclear(_r) do { \ - php_pqres_object_t *_o = PQresultInstanceData((_r), php_pqconn_event); \ - if (_o) { \ - php_pq_object_delref(_o); \ - } else { \ - PQclear(_r); \ - } \ -} while(0) extern zend_class_entry *php_pqres_class_entry; extern php_pqres_object_t *php_pqres_create_object_ex(zend_class_entry *ce, php_pqres_t *intern); diff --git a/src/php_pqstm.c b/src/php_pqstm.c index dff5375..fbab27e 100644 --- a/src/php_pqstm.c +++ b/src/php_pqstm.c @@ -51,8 +51,8 @@ static void php_pqstm_deallocate(php_pqstm_object_t *obj, zend_bool async, zend_ } else { PGresult *res; - if ((res = PQexec(obj->intern->conn->intern->conn, smart_str_v(&cmd)))) { - PHP_PQclear(res); + if ((res = php_pq_exec(obj->intern->conn->intern->conn, smart_str_v(&cmd)))) { + php_pq_clear_res(res); } else if (!silent) { throw_exce(EX_RUNTIME, "Failed to deallocate statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } @@ -252,7 +252,7 @@ static PHP_METHOD(pqstm, exec) { PGresult *res; php_pq_params_set_params(obj->intern->params, zparams ? Z_ARRVAL_P(zparams) : &obj->intern->bound); - res = PQexecPrepared(obj->intern->conn->intern->conn, obj->intern->name, obj->intern->params->param.count, (const char *const*) obj->intern->params->param.strings, NULL, NULL, 0); + res = php_pq_exec_prepared(obj->intern->conn->intern->conn, obj->intern->name, obj->intern->params->param.count, (const char *const*) obj->intern->params->param.strings, NULL, NULL, 0); php_pq_params_set_params(obj->intern->params, NULL); if (!res) { @@ -340,7 +340,7 @@ static PHP_METHOD(pqstm, desc) { add_next_index_long(return_value, PQparamtype(res, p)); } } - PHP_PQclear(res); + php_pq_clear_res(res); php_pqconn_notify_listeners(obj->intern->conn); } } diff --git a/src/php_pqtxn.c b/src/php_pqtxn.c index 5b12545..7b57ebf 100644 --- a/src/php_pqtxn.c +++ b/src/php_pqtxn.c @@ -55,10 +55,10 @@ static void php_pqtxn_object_free(zend_object *o) #endif if (obj->intern) { if (obj->intern->open && obj->intern->conn->intern) { - PGresult *res = PQexec(obj->intern->conn->intern->conn, "ROLLBACK"); + PGresult *res = php_pq_exec(obj->intern->conn->intern->conn, "ROLLBACK"); if (res) { - PHP_PQclear(res); + php_pq_clear_res(res); } } php_pq_object_delref(obj->intern->conn); @@ -124,13 +124,13 @@ static void php_pqtxn_object_write_isolation(zval *object, void *o, zval *value) switch ((obj->intern->isolation = zval_get_long(value))) { case PHP_PQTXN_READ_COMMITTED: - res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION ISOLATION LEVEL READ COMMITED"); + res = php_pq_exec(obj->intern->conn->intern->conn, "SET TRANSACTION ISOLATION LEVEL READ COMMITED"); break; case PHP_PQTXN_REPEATABLE_READ: - res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION ISOLATION LEVEL REPEATABLE READ"); + res = php_pq_exec(obj->intern->conn->intern->conn, "SET TRANSACTION ISOLATION LEVEL REPEATABLE READ"); break; case PHP_PQTXN_SERIALIZABLE: - res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE"); + res = php_pq_exec(obj->intern->conn->intern->conn, "SET TRANSACTION ISOLATION LEVEL SERIALIZABLE"); break; default: obj->intern->isolation = orig; @@ -140,7 +140,7 @@ static void php_pqtxn_object_write_isolation(zval *object, void *o, zval *value) if (res) { php_pqres_success(res); - PHP_PQclear(res); + php_pq_clear_res(res); } } @@ -150,14 +150,14 @@ static void php_pqtxn_object_write_readonly(zval *object, void *o, zval *value) PGresult *res; if ((obj->intern->readonly = z_is_true(value))) { - res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION READ ONLY"); + res = php_pq_exec(obj->intern->conn->intern->conn, "SET TRANSACTION READ ONLY"); } else { - res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION READ WRITE"); + res = php_pq_exec(obj->intern->conn->intern->conn, "SET TRANSACTION READ WRITE"); } if (res) { php_pqres_success(res); - PHP_PQclear(res); + php_pq_clear_res(res); } } @@ -167,14 +167,14 @@ static void php_pqtxn_object_write_deferrable(zval *object, void *o, zval *value PGresult *res; if ((obj->intern->deferrable = z_is_true(value))) { - res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION DEFERRABLE"); + res = php_pq_exec(obj->intern->conn->intern->conn, "SET TRANSACTION DEFERRABLE"); } else { - res = PQexec(obj->intern->conn->intern->conn, "SET TRANSACTION NOT DEFERRABLE"); + res = php_pq_exec(obj->intern->conn->intern->conn, "SET TRANSACTION NOT DEFERRABLE"); } if (res) { php_pqres_success(res); - PHP_PQclear(res); + php_pq_clear_res(res); } } @@ -265,13 +265,13 @@ static PHP_METHOD(pqtxn, savepoint) { smart_str_appends(&cmd, "\""); smart_str_0(&cmd); - res = PQexec(obj->intern->conn->intern->conn, smart_str_v(&cmd)); + res = php_pq_exec(obj->intern->conn->intern->conn, smart_str_v(&cmd)); if (!res) { throw_exce(EX_RUNTIME, "Failed to create %s (%s)", smart_str_v(&cmd), PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { php_pqres_success(res); - PHP_PQclear(res); + php_pq_clear_res(res); } smart_str_free(&cmd); @@ -336,14 +336,14 @@ static PHP_METHOD(pqtxn, commit) { zend_bool just_release_sp = !!obj->intern->savepoint; if (!just_release_sp) { - res = PQexec(obj->intern->conn->intern->conn, "COMMIT"); + res = php_pq_exec(obj->intern->conn->intern->conn, "COMMIT"); } else { smart_str_appends(&cmd, "RELEASE SAVEPOINT \""); smart_str_append_unsigned(&cmd, obj->intern->savepoint--); smart_str_appends(&cmd, "\""); smart_str_0(&cmd); - res = PQexec(obj->intern->conn->intern->conn, smart_str_v(&cmd)); + res = php_pq_exec(obj->intern->conn->intern->conn, smart_str_v(&cmd)); } if (!res) { @@ -354,7 +354,7 @@ static PHP_METHOD(pqtxn, commit) { obj->intern->open = 0; } } - PHP_PQclear(res); + php_pq_clear_res(res); } smart_str_free(&cmd); @@ -434,14 +434,14 @@ static PHP_METHOD(pqtxn, rollback) { zend_bool just_release_sp = !!obj->intern->savepoint; if (!just_release_sp) { - res = PQexec(obj->intern->conn->intern->conn, "ROLLBACK"); + res = php_pq_exec(obj->intern->conn->intern->conn, "ROLLBACK"); } else { smart_str_appends(&cmd, "ROLLBACK TO SAVEPOINT \""); smart_str_append_unsigned(&cmd, obj->intern->savepoint--); smart_str_appends(&cmd, "\""); smart_str_0(&cmd); - res = PQexec(obj->intern->conn->intern->conn, smart_str_v(&cmd)); + res = php_pq_exec(obj->intern->conn->intern->conn, smart_str_v(&cmd)); } if (!res) { @@ -452,7 +452,7 @@ static PHP_METHOD(pqtxn, rollback) { obj->intern->open = 0; } } - PHP_PQclear(res); + php_pq_clear_res(res); } smart_str_free(&cmd); @@ -525,7 +525,7 @@ static PHP_METHOD(pqtxn, exportSnapshot) { if (!obj->intern) { throw_exce(EX_UNINITIALIZED, "pq\\Transaction not initialized"); } else { - PGresult *res = PQexec(obj->intern->conn->intern->conn, "SELECT pg_export_snapshot()"); + PGresult *res = php_pq_exec(obj->intern->conn->intern->conn, "SELECT pg_export_snapshot()"); if (!res) { throw_exce(EX_RUNTIME, "Failed to export transaction snapshot (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); @@ -534,7 +534,7 @@ static PHP_METHOD(pqtxn, exportSnapshot) { RETVAL_STRING(PQgetvalue(res, 0, 0)); } - PHP_PQclear(res); + php_pq_clear_res(res); } php_pqconn_notify_listeners(obj->intern->conn); @@ -599,13 +599,13 @@ static PHP_METHOD(pqtxn, importSnapshot) { smart_str_appends(&cmd, sid); smart_str_0(&cmd); - res = PQexec(obj->intern->conn->intern->conn, smart_str_v(&cmd)); + res = php_pq_exec(obj->intern->conn->intern->conn, smart_str_v(&cmd)); if (!res) { throw_exce(EX_RUNTIME, "Failed to import transaction snapshot (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn)); } else { php_pqres_success(res); - PHP_PQclear(res); + php_pq_clear_res(res); } smart_str_free(&cmd); @@ -731,7 +731,7 @@ static PHP_METHOD(pqtxn, createLOB) { lob->lofd = lofd; lob->loid = loid; - php_pq_object_addref(obj TSRMLS_CC); + php_pq_object_addref(obj); lob->txn = obj; RETVAL_OBJ(&php_pqlob_create_object_ex(php_pqlob_class_entry, lob)->zo); diff --git a/src/php_pqtypes.c b/src/php_pqtypes.c index ef169d3..3f05248 100644 --- a/src/php_pqtypes.c +++ b/src/php_pqtypes.c @@ -230,17 +230,17 @@ static PHP_METHOD(pqtypes, refresh) { PGresult *res; if (!nsp || !zend_hash_num_elements(nsp)) { - res = PQexec(obj->intern->conn->intern->conn, PHP_PQ_TYPES_QUERY " and nspname in ('public', 'pg_catalog')"); + res = php_pq_exec(obj->intern->conn->intern->conn, PHP_PQ_TYPES_QUERY " and nspname in ('public', 'pg_catalog')"); } else { smart_str str = {0}; php_pq_params_t *params = php_pq_params_init(&obj->intern->conn->intern->converters, NULL, NULL); smart_str_appends(&str, PHP_PQ_TYPES_QUERY " and nspname in("); - zend_hash_apply_with_arguments(nsp TSRMLS_CC, apply_nsp, 2, params, &str); + zend_hash_apply_with_arguments(nsp, apply_nsp, 2, params, &str); smart_str_appendc(&str, ')'); smart_str_0(&str); - res = PQexecParams(obj->intern->conn->intern->conn, smart_str_v(&str), params->param.count, params->type.oids, (const char *const*) params->param.strings, NULL, NULL, 0); + res = php_pq_exec_params(obj->intern->conn->intern->conn, smart_str_v(&str), params->param.count, params->type.oids, (const char *const*) params->param.strings, NULL, NULL, 0); smart_str_free(&str); php_pq_params_free(¶ms); @@ -264,7 +264,7 @@ static PHP_METHOD(pqtypes, refresh) { } } - PHP_PQclear(res); + php_pq_clear_res(res); php_pqconn_notify_listeners(obj->intern->conn); } } @@ -293,7 +293,7 @@ PHP_MINIT_FUNCTION(pqtypes) php_pqtypes_class_entry->create_object = php_pqtypes_create_object; /* - zend_class_implements(php_pqtypes_class_entry TSRMLS_CC, 1, zend_ce_arrayaccess); + zend_class_implements(php_pqtypes_class_entry, 1, zend_ce_arrayaccess); */ memcpy(&php_pqtypes_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); diff --git a/tests/callback001.phpt b/tests/callback001.phpt new file mode 100644 index 0000000..a47b4c2 --- /dev/null +++ b/tests/callback001.phpt @@ -0,0 +1,37 @@ +--TEST-- +callback sanity +--SKIPIF-- + +--FILE-- +execAsync("select 1; select 2", function($r) { + print_r($r->fetchAll()); +}); +$c->exec("select 3"); + +?> +===DONE=== +--EXPECT-- +Test +Array +( + [0] => Array + ( + [0] => 1 + ) + +) +Array +( + [0] => Array + ( + [0] => 2 + ) + +) +===DONE=== diff --git a/tests/callback002.phpt b/tests/callback002.phpt new file mode 100644 index 0000000..7d7903b --- /dev/null +++ b/tests/callback002.phpt @@ -0,0 +1,44 @@ +--TEST-- +callback sanity +--SKIPIF-- + +--FILE-- +execAsync("select 1; select 2", function($r) { + print_r($r->fetchAll()); +}); +try { + $c->execAsync("select 3; select 4", function($r) { + + }); +} catch (Exception $e) { + printf("%s\n", $e->getMessage()); +} +$c->exec(""); +?> +===DONE=== +--EXPECT-- +Test +Failed to execute query (another command is already in progress) +Array +( + [0] => Array + ( + [0] => 1 + ) + +) +Array +( + [0] => Array + ( + [0] => 2 + ) + +) +===DONE=== diff --git a/tests/callback003.phpt b/tests/callback003.phpt new file mode 100644 index 0000000..97b0aeb --- /dev/null +++ b/tests/callback003.phpt @@ -0,0 +1,84 @@ +--TEST-- +callback sanity +--SKIPIF-- + +--FILE-- +execAsync("select 1; select 2", function($r) use($c) { + echo "CALLBACK 1\n"; + print_r($r->fetchAll()); + $c->exec("select 'bug'"); + try { + $c->execAsync("select 3; select 4", function($r) { + echo "CALLBACK 2\n"; + print_r($r->fetchAll()); + }); + } catch (Exception $e) { + printf("%s\n", $e->getMessage()); + } +}); +$c->exec("select 'end'"); +?> +===DONE=== +--EXPECT-- +Test +CALLBACK 1 +Array +( + [0] => Array + ( + [0] => 1 + ) + +) +CALLBACK 1 +Array +( + [0] => Array + ( + [0] => 2 + ) + +) +CALLBACK 2 +Array +( + [0] => Array + ( + [0] => 3 + ) + +) +CALLBACK 2 +Array +( + [0] => Array + ( + [0] => 4 + ) + +) +CALLBACK 2 +Array +( + [0] => Array + ( + [0] => 3 + ) + +) +CALLBACK 2 +Array +( + [0] => Array + ( + [0] => 4 + ) + +) +===DONE=== \ No newline at end of file