1
0
mirror of https://github.com/danog/ext-pq.git synced 2024-12-02 09:18:02 +01:00

Merge branch 'v1.0.x'

This commit is contained in:
Michael Wallner 2016-05-03 14:49:28 +02:00
commit 8d0dbf7286
No known key found for this signature in database
GPG Key ID: 480E3E14B0A4C7C7
20 changed files with 379 additions and 121 deletions

View File

@ -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;
}
}

View File

@ -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

View File

@ -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};

View File

@ -16,15 +16,6 @@
#include <libpq-fe.h>
#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);

View File

@ -18,7 +18,7 @@
#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"

View File

@ -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;
}

View File

@ -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));

View File

@ -20,6 +20,7 @@
#include <ext/raphf/php_raphf.h>
#include "php_pq_object.h"
#include "php_pq_callback.h"
#include "php_pq_object.h"
#include "php_pq_params.h"
typedef struct php_pqconn {

View File

@ -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);

View File

@ -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;

View File

@ -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));

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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(&params);
@ -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));

37
tests/callback001.phpt Normal file
View File

@ -0,0 +1,37 @@
--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===

44
tests/callback002.phpt Normal file
View File

@ -0,0 +1,44 @@
--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===

84
tests/callback003.phpt Normal file
View File

@ -0,0 +1,84 @@
--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===