zend_object zo;
PGconn *conn;
int (*poller)(PGconn *);
- unsigned blocking:1;
+ unsigned async:1;
} php_pqconn_object_t;
typedef enum php_pqres_fetch {
if (conn) {
o->conn = conn;
- o->blocking = !PQisnonblocking(o->conn);
+ o->async = !PQisnonblocking(o->conn);
}
ov.handle = zend_objects_store_put((zend_object *) o, NULL, php_pqconn_object_free, NULL TSRMLS_CC);
RETVAL_LONG(PQtransactionStatus(obj->conn));
}
-static void php_pqconn_object_read_socket(void *o, zval *return_value TSRMLS_DC)
-{
- php_pqconn_object_t *obj = o;
- php_stream *stream;
- int socket = PQsocket(obj->conn);
-
- if ((stream = php_stream_fopen_from_fd(socket, "r+b", NULL))) {
- php_stream_to_zval(stream, return_value);
- } else {
- RETVAL_NULL();
- }
-}
-
static void php_pqconn_object_read_error_message(void *o, zval *return_value TSRMLS_DC)
{
php_pqconn_object_t *obj = o;
if (!obj->conn) {
zend_error(E_WARNING, "Connection not initialized");
- } else if (SUCCESS == zend_hash_find(&php_pqconn_object_prophandlers, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void *) &handler)) {
+ } else if ((SUCCESS == zend_hash_find(&php_pqconn_object_prophandlers, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void *) &handler)) && handler->read) {
if (type == BP_VAR_R) {
ALLOC_ZVAL(return_value);
Z_SET_REFCOUNT_P(return_value, 0);
}
}
+static STATUS php_pqconn_update_socket(zval *this_ptr, php_pqconn_object_t *obj TSRMLS_DC)
+{
+ zval *zsocket, zmember;
+ php_stream *stream;
+ STATUS retval;
+ int socket;
+
+ if (!obj) {
+ obj = zend_object_store_get_object(getThis() TSRMLS_CC);
+ }
+
+ INIT_PZVAL(&zmember);
+ ZVAL_STRINGL(&zmember, "socket", sizeof("socket")-1, 0);
+ MAKE_STD_ZVAL(zsocket);
+
+ if ((CONNECTION_BAD != PQstatus(obj->conn))
+ && (-1 < (socket = PQsocket(obj->conn)))
+ && (stream = php_stream_fopen_from_fd(socket, "r+b", NULL))) {
+ php_stream_to_zval(stream, zsocket);
+ retval = SUCCESS;
+ } else {
+ ZVAL_NULL(zsocket);
+ retval = FAILURE;
+ }
+ zend_get_std_object_handlers()->write_property(getThis(), &zmember, zsocket, NULL TSRMLS_CC);
+ zval_ptr_dtor(&zsocket);
+
+ return retval;
+}
+
ZEND_BEGIN_ARG_INFO_EX(ai_pqconn_construct, 0, 0, 1)
ZEND_ARG_INFO(0, dsn)
- ZEND_ARG_INFO(0, block)
+ ZEND_ARG_INFO(0, async)
ZEND_END_ARG_INFO();
static PHP_METHOD(pqconn, __construct) {
zend_error_handling zeh;
char *dsn_str;
int dsn_len;
- zend_bool block = 1;
+ zend_bool async = 0;
zend_replace_error_handling(EH_THROW, NULL, &zeh TSRMLS_CC);
- if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &dsn_str, &dsn_len, &block)) {
+ if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &dsn_str, &dsn_len, &async)) {
php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
if (obj->conn) {
PQfinish(obj->conn);
}
- if ((obj->blocking = block)) {
- obj->conn = PQconnectdb(dsn_str);
- } else {
+ if ((obj->async = async)) {
obj->conn = PQconnectStart(dsn_str);
obj->poller = (int (*)(PGconn*)) PQconnectPoll;
+ } else {
+ obj->conn = PQconnectdb(dsn_str);
}
-
- if (CONNECTION_BAD == PQstatus(obj->conn)) {
+
+ if (SUCCESS != php_pqconn_update_socket(getThis(), obj TSRMLS_CC)) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection failed: %s", PQerrorMessage(obj->conn));
}
}
php_pqconn_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
if (obj->conn) {
- if (obj->blocking) {
+ if (obj->async) {
+ if (PQresetStart(obj->conn)) {
+ obj->poller = (int (*)(PGconn*)) PQresetPoll;
+ RETURN_TRUE;
+ }
+ } else {
PQreset(obj->conn);
- RETURN_TRUE; /* probably ;) */
- } if (PQresetStart(obj->conn)) {
- obj->poller = (int (*)(PGconn*)) PQresetPoll;
- RETURN_TRUE;
+
+ if (CONNECTION_OK == PQstatus(obj->conn)) {
+ RETURN_TRUE;
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection reset failed: %s", PQerrorMessage(obj->conn));
+ }
}
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not initialized");
if (obj->conn) {
if (obj->poller) {
- RETURN_LONG(obj->poller(obj->conn));
+ if (obj->poller == PQconsumeInput) {
+ RETURN_LONG(obj->poller(obj->conn) * PGRES_POLLING_OK);
+ } else {
+ RETURN_LONG(obj->poller(obj->conn));
+ }
} else {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "No asynchronous operation active");
}
case PGRES_BAD_RESPONSE:
case PGRES_NONFATAL_ERROR:
case PGRES_FATAL_ERROR:
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: %s", PQresStatus(PQresultStatus(res)), PQresultErrorMessage(res));
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", PQresultErrorMessage(res));
return FAILURE;
default:
return SUCCESS;
zend_hash_add(&php_pqconn_object_prophandlers, "transactionStatus", sizeof("transactionStatus"), (void *) &ph, sizeof(ph), NULL);
zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("socket"), ZEND_ACC_PUBLIC TSRMLS_CC);
- ph.read = php_pqconn_object_read_socket;
+ ph.read = NULL; /* forward to std prophandler */
zend_hash_add(&php_pqconn_object_prophandlers, "socket", sizeof("socket"), (void *) &ph, sizeof(ph), NULL);
zend_declare_property_null(php_pqconn_class_entry, ZEND_STRL("errorMessage"), ZEND_ACC_PUBLIC TSRMLS_CC);