</stability>
<license uri="http://copyfree.org/content/standard/licenses/2bsd/license.txt">BSD-2-Clause</license>
<notes><![CDATA[
-*
+* Fix github issue #9 (execAsync - gets another result)
]]></notes>
<contents>
<dir name="/">
<file role="test" name="basic001.phpt" />
<file role="test" name="basic002.phpt" />
<file role="test" name="bound002.phpt" />
+ <file role="test" name="callback001.phpt" />
+ <file role="test" name="callback002.phpt" />
+ <file role="test" name="callback003.phpt" />
<file role="test" name="cancel001.phpt" />
<file role="test" name="conv001.phpt" />
<file role="test" name="copy001.phpt" />
#ifndef PHP_PQ_H
#define PHP_PQ_H
-#define PHP_PQ_VERSION "1.0.0dev"
+#define PHP_PQ_VERSION "1.0.1dev"
#ifdef PHP_WIN32
# define PHP_PQ_API __declspec(dllexport)
zend_bool php_pq_callback_is_locked(php_pq_callback_t *cb TSRMLS_DC)
{
- 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 TSRMLS_CC);
+ 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;
+ }
+
+ closure = zend_get_closure_method_def(cb->fci.function_name TSRMLS_CC);
+ if (closure->type != ZEND_USER_FUNCTION) {
+ return 0;
+ }
- while (ex) {
- if (ex->op_array == &closure->op_array) {
- return 1;
- }
- ex = ex->prev_execute_data;
+ for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) {
+ if (ex->op_array == &closure->op_array) {
+ return 1;
}
}
}
- return 0;
+
+ if (!php_pq_callback_is_recurrent(cb)) {
+ return 0;
+ }
+ return php_pq_callback_is_locked(cb->recursion TSRMLS_CC);
}
void php_pq_callback_recurse(php_pq_callback_t *old, php_pq_callback_t *new TSRMLS_DC)
{
- 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) {
+ if (php_pq_callback_is_locked(old TSRMLS_CC)) {
+ php_pq_callback_recurse_ex(old, new TSRMLS_CC);
+ } else {
php_pq_callback_dtor(old);
- php_pq_callback_addref(new);
+ 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 TSRMLS_DC)
+{
+ if (php_pq_callback_is_enabled(cb)) {
+ php_pq_callback_recurse_ex(cb, NULL TSRMLS_CC);
+ }
+}
+
+extern void php_pq_callback_recurse_ex(php_pq_callback_t *old, php_pq_callback_t *new TSRMLS_DC)
+{
+ php_pq_callback_t *tmp = emalloc(sizeof(*tmp));
+
+ if (new) {
+ memcpy(tmp, old, sizeof(*tmp));
memcpy(old, new, sizeof(*old));
- new->fci.size = 0;
+ old->recursion = tmp;
+
+ php_pq_callback_addref(old);
+ php_pq_callback_disable(tmp TSRMLS_CC);
} else {
- php_pq_callback_dtor(old);
+ memcpy(tmp, old, sizeof(*tmp));
+ memset(old, 0, sizeof(*old));
+ old->recursion = tmp;
}
}
extern zval *php_pq_callback_to_zval(php_pq_callback_t *cb);
extern zend_bool php_pq_callback_is_locked(php_pq_callback_t *cb TSRMLS_DC);
extern void php_pq_callback_recurse(php_pq_callback_t *old, php_pq_callback_t *new TSRMLS_DC);
+extern zend_bool php_pq_callback_is_enabled(php_pq_callback_t *cb);
+extern void php_pq_callback_disable(php_pq_callback_t *cb TSRMLS_DC);
+extern void php_pq_callback_recurse_ex(php_pq_callback_t *old, php_pq_callback_t *new TSRMLS_DC);
+extern zend_bool php_pq_callback_is_recurrent(php_pq_callback_t *cb);
#endif
#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) {
+ TSRMLS_FETCH();
+ php_pq_object_delref(o TSRMLS_CC);
+ } 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)) {
+ TSRMLS_FETCH_FROM_CTX(evdata->ts);
+
+ if (php_pq_callback_is_locked(&evdata->obj->intern->onevent TSRMLS_CC)) {
+ php_pq_callback_disable(&evdata->obj->intern->onevent TSRMLS_CC);
+ } 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);
#include "php_pqres.h"
+/* 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);
+
/* TSRM morony */
#if PHP_VERSION_ID >= 50700
# define z_is_true(z) zend_is_true(z TSRMLS_CC)
#include <php.h>
#include <ext/standard/info.h>
-#include <libpq-fe.h>
+#include <libpq-events.h>
#include "php_pq.h"
#include "php_pq_misc.h"
static void php_pqconn_wakeup(php_persistent_handle_factory_t *f, void **handle TSRMLS_DC)
{
PGresult *res = PQexec(*handle, "");
- PHP_PQclear(res);
+ php_pq_clear_res(res);
if (CONNECTION_OK != PQstatus(*handle)) {
PQreset(*handle);
PGresult *res = unlisten(obj->intern->conn, key->arKey, key->nKeyLength - 1 TSRMLS_CC);
if (res) {
- PHP_PQclear(res);
+ php_pq_clear_res(res);
}
return ZEND_HASH_APPLY_REMOVE;
}
/* clean up async results */
while ((res = PQgetResult(*handle))) {
- PHP_PQclear(res);
+ php_pq_clear_res(res);
}
/* clean up transaction & session */
}
if (res) {
- PHP_PQclear(res);
+ php_pq_clear_res(res);
}
if (evdata) {
if (res) {
php_pqres_success(res TSRMLS_CC);
- PHP_PQclear(res);
+ php_pq_clear_res(res);
}
}
}
smart_str_appends(&cmd, quoted_channel);
smart_str_0(&cmd);
- res = PQexec(obj->intern->conn, cmd.c);
+ res = php_pq_exec(obj->intern->conn, cmd.c);
smart_str_free(&cmd);
PQfreemem(quoted_channel);
obj->intern->poller = PQconsumeInput;
php_pqconn_add_listener(obj, channel_str, channel_len, &listener TSRMLS_CC);
}
- PHP_PQclear(res);
+ php_pq_clear_res(res);
}
php_pqconn_notify_listeners(obj TSRMLS_CC);
throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to notify listeners (%s)", PHP_PQerrorMessage(obj->intern->conn));
} else {
php_pqres_success(res TSRMLS_CC);
- PHP_PQclear(res);
+ php_pq_clear_res(res);
}
php_pqconn_notify_listeners(obj TSRMLS_CC);
if (!obj->intern) {
throw_exce(EX_UNINITIALIZED TSRMLS_CC, "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 TSRMLS_CC, "Failed to execute query (%s)", PHP_PQerrorMessage(obj->intern->conn));
} else if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), &return_value TSRMLS_CC);
} else {
- PHP_PQclear(res);
+ php_pq_clear_res(res);
}
php_pqconn_notify_listeners(obj TSRMLS_CC);
if (SUCCESS == php_pqres_success(res TSRMLS_CC)) {
php_pq_object_to_zval_no_addref(PQresultInstanceData(res, php_pqconn_event), &return_value TSRMLS_CC);
} else {
- PHP_PQclear(res);
+ php_pq_clear_res(res);
}
php_pqconn_notify_listeners(obj TSRMLS_CC);
obj = zend_object_store_get_object(object TSRMLS_CC);
}
- 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 TSRMLS_CC, "Failed to prepare statement (%s)", PHP_PQerrorMessage(obj->intern->conn));
} else {
rv = php_pqres_success(res TSRMLS_CC);
- PHP_PQclear(res);
+ php_pq_clear_res(res);
php_pqconn_notify_listeners(obj TSRMLS_CC);
}
obj = zend_object_store_get_object(object TSRMLS_CC);
}
- res = PQexec(obj->intern->conn, decl);
+ res = php_pq_exec(obj->intern->conn, decl);
if (!res) {
rv = FAILURE;
throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to declare cursor (%s)", PHP_PQerrorMessage(obj->intern->conn));
} else {
rv = php_pqres_success(res TSRMLS_CC);
- PHP_PQclear(res);
+ php_pq_clear_res(res);
php_pqconn_notify_listeners(obj TSRMLS_CC);
}
smart_str_appends(&cmd, " DEFERRABLE");
smart_str_0(&cmd);
- res = PQexec(conn_obj->intern->conn, cmd.c);
+ res = php_pq_exec(conn_obj->intern->conn, cmd.c);
if (!res) {
throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to start transaction (%s)", PHP_PQerrorMessage(conn_obj->intern->conn));
} else {
rv = php_pqres_success(res TSRMLS_CC);
- PHP_PQclear(res);
+ php_pq_clear_res(res);
php_pqconn_notify_listeners(conn_obj TSRMLS_CC);
}
#include <ext/raphf/php_raphf.h>
#include "php_pq_callback.h"
+#include "php_pq_object.h"
#include "php_pq_params.h"
typedef struct php_pqconn {
}
/* async callback */
- if (data->obj->intern->onevent.fci.size > 0) {
+ if (php_pq_callback_is_enabled(&data->obj->intern->onevent)) {
zval *res = NULL;
php_pq_object_to_zval(obj, &res TSRMLS_CC);
smart_str_appendl(&cmd, opt_str, opt_len);
smart_str_0(&cmd);
- res = PQexec(conn_obj->intern->conn, cmd.c);
+ res = php_pq_exec(conn_obj->intern->conn, cmd.c);
if (!res) {
throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to start %s (%s)", cmd.c, PHP_PQerrorMessage(obj->intern->conn->intern->conn));
php_pq_object_addref(conn_obj TSRMLS_CC);
}
- PHP_PQclear(res);
+ php_pq_clear_res(res);
}
smart_str_free(&cmd);
throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to fetch COPY result (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
} else {
php_pqres_success(res TSRMLS_CC);
- PHP_PQclear(res);
+ php_pq_clear_res(res);
}
}
throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to fetch COPY result (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
} else {
php_pqres_success(res TSRMLS_CC);
- PHP_PQclear(res);
+ php_pq_clear_res(res);
RETVAL_FALSE;
}
break;
throw_exce(EX_IO TSRMLS_CC, "Failed to close cursor (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
}
} else {
- if ((res = PQexec(obj->intern->conn->intern->conn, cmd.c))) {
- PHP_PQclear(res);
+ if ((res = php_pq_exec(obj->intern->conn->intern->conn, cmd.c))) {
+ php_pq_clear_res(res);
} else if (!silent) {
throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to close cursor (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
}
obj->intern->conn->intern->poller = PQconsumeInput;
}
} else {
- PGresult *res = PQexec(obj->intern->conn->intern->conn, cmd.c);
+ PGresult *res = php_pq_exec(obj->intern->conn->intern->conn, cmd.c);
if (!res) {
throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to %s cursor (%s)", *action == 'f' ? "fetch from" : "move in", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
#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 TSRMLS_CC); \
- } else { \
- PQclear(_r); \
- } \
-} while(0)
extern zend_class_entry *php_pqres_class_entry;
extern zend_object_value php_pqres_create_object_ex(zend_class_entry *ce, php_pqres_t *intern, php_pqres_object_t **ptr TSRMLS_DC);
} else {
PGresult *res;
- if ((res = PQexec(obj->intern->conn->intern->conn, cmd.c))) {
- PHP_PQclear(res);
+ if ((res = php_pq_exec(obj->intern->conn->intern->conn, cmd.c))) {
+ php_pq_clear_res(res);
} else if (!silent) {
throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to deallocate statement (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
}
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) {
add_next_index_long(return_value, PQparamtype(res, p));
}
}
- PHP_PQclear(res);
+ php_pq_clear_res(res);
php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC);
}
}
#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 TSRMLS_CC);
switch ((obj->intern->isolation = Z_LVAL_P(zisolation))) {
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;
if (res) {
php_pqres_success(res TSRMLS_CC);
- PHP_PQclear(res);
+ php_pq_clear_res(res);
}
}
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 TSRMLS_CC);
- PHP_PQclear(res);
+ php_pq_clear_res(res);
}
}
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 TSRMLS_CC);
- PHP_PQclear(res);
+ php_pq_clear_res(res);
}
}
smart_str_appends(&cmd, "\"");
smart_str_0(&cmd);
- res = PQexec(obj->intern->conn->intern->conn, cmd.c);
+ res = php_pq_exec(obj->intern->conn->intern->conn, cmd.c);
if (!res) {
throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to create %s (%s)", cmd.c, PHP_PQerrorMessage(obj->intern->conn->intern->conn));
} else {
php_pqres_success(res TSRMLS_CC);
- PHP_PQclear(res);
+ php_pq_clear_res(res);
}
smart_str_free(&cmd);
smart_str cmd = {0};
if (!obj->intern->savepoint) {
- 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, cmd.c);
+ res = php_pq_exec(obj->intern->conn->intern->conn, cmd.c);
}
if (!res) {
obj->intern->open = 0;
}
}
- PHP_PQclear(res);
+ php_pq_clear_res(res);
}
smart_str_free(&cmd);
smart_str cmd = {0};
if (!obj->intern->savepoint) {
- 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, cmd.c);
+ res = php_pq_exec(obj->intern->conn->intern->conn, cmd.c);
}
if (!res) {
obj->intern->open = 0;
}
}
- PHP_PQclear(res);
+ php_pq_clear_res(res);
}
smart_str_free(&cmd);
if (!obj->intern) {
throw_exce(EX_UNINITIALIZED TSRMLS_CC, "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 TSRMLS_CC, "Failed to export transaction snapshot (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
RETVAL_STRING(PQgetvalue(res, 0, 0), 1);
}
- PHP_PQclear(res);
+ php_pq_clear_res(res);
}
php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC);
smart_str_appends(&cmd, sid);
smart_str_0(&cmd);
- res = PQexec(obj->intern->conn->intern->conn, cmd.c);
+ res = php_pq_exec(obj->intern->conn->intern->conn, cmd.c);
if (!res) {
throw_exce(EX_RUNTIME TSRMLS_CC, "Failed to import transaction snapshot (%s)", PHP_PQerrorMessage(obj->intern->conn->intern->conn));
} else {
php_pqres_success(res TSRMLS_CC);
- PHP_PQclear(res);
+ php_pq_clear_res(res);
}
smart_str_free(&cmd);
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 TSRMLS_CC);
smart_str_appendc(&str, ')');
smart_str_0(&str);
- res = PQexecParams(obj->intern->conn->intern->conn, str.c, 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, str.c, params->param.count, params->type.oids, (const char *const*) params->param.strings, NULL, NULL, 0);
smart_str_free(&str);
php_pq_params_free(¶ms);
}
}
- PHP_PQclear(res);
+ php_pq_clear_res(res);
php_pqconn_notify_listeners(obj->intern->conn TSRMLS_CC);
}
}
--- /dev/null
+--TEST--
+callback sanity
+--SKIPIF--
+<?php include "_skipif.inc"; ?>
+--FILE--
+<?php
+echo "Test\n";
+
+include "_setup.inc";
+
+$c = new pq\Connection(PQ_DSN);
+$c->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===
--- /dev/null
+--TEST--
+callback sanity
+--SKIPIF--
+<?php include "_skipif.inc"; ?>
+--FILE--
+<?php
+echo "Test\n";
+
+include "_setup.inc";
+
+$c = new pq\Connection(PQ_DSN);
+$c->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===
--- /dev/null
+--TEST--
+callback sanity
+--SKIPIF--
+<?php include "_skipif.inc"; ?>
+--FILE--
+<?php
+echo "Test\n";
+
+include "_setup.inc";
+
+$c = new pq\Connection(PQ_DSN);
+$c->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
-Subproject commit 7d1a61ddce20446912ed1d5c988f801903972a34
+Subproject commit 23c2876aaa0808bcfedc1c5c30da6e8234341a13