I really need async query functions for pgsql, so I wrote it. All functions are *simple* libpq wrapper. This patch is safe to apply.
Async query can be very useful to improve performance, since pg_sendquery() returns immediately, then user can use pg_getresult() to get result later. (Especially when user have multiple db server) Missing feature is that raise warning or prohibit async query on persistent connection, since it can cause problems. I haven't implemented this, yet. Could anyone apply this patch? Thank you. -- Yasuo Ohgaki
Index: pgsql.c =================================================================== RCS file: /repository/php4/ext/pgsql/pgsql.c,v retrieving revision 1.130 diff -u -r1.130 pgsql.c --- pgsql.c 11 Oct 2001 23:33:40 -0000 1.130 +++ pgsql.c 3 Nov 2001 18:19:20 -0000 @@ -94,6 +94,17 @@ PHP_FALIAS(pg_clientencoding, pg_client_encoding, NULL) PHP_FALIAS(pg_setclientencoding, pg_set_client_encoding, NULL) #endif + /* asyncronous query interface */ + PHP_FE(pg_sendquery, NULL) + PHP_FE(pg_setnonblocking, NULL) + PHP_FE(pg_isnonblocking, NULL) + PHP_FE(pg_getresult, NULL) + PHP_FE(pg_isbusy, NULL) + PHP_FE(pg_flush, NULL) + PHP_FE(pg_socket, NULL) + PHP_FE(pg_consumeinput, NULL) + PHP_FE(pg_requestcancel, NULL) + PHP_FE(pg_notifies, NULL) {NULL, NULL, NULL} }; /* }}} */ @@ -195,8 +206,9 @@ PGG(ignore_notices) = 1; PQexec(link,"BEGIN;ROLLBACK;"); + PQflush(link); PGG(ignore_notices) = 0; - + return 0; } /* }}} */ @@ -226,7 +238,8 @@ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("pgsql.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateInt, allow_persistent, php_pgsql_globals, pgsql_globals) STD_PHP_INI_ENTRY_EX("pgsql.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateInt, max_persistent, php_pgsql_globals, pgsql_globals, display_link_numbers) - STD_PHP_INI_ENTRY_EX("pgsql.max_links", "-1", PHP_INI_SYSTEM, OnUpdateInt, max_links, php_pgsql_globals, pgsql_globals, display_link_numbers) + STD_PHP_INI_ENTRY_EX("pgsql.max_links", "-1", PHP_INI_SYSTEM, + OnUpdateInt, max_links, php_pgsql_globals, + pgsql_globals, display_link_numbers) + STD_PHP_INI_BOOLEAN("pgsql.allow_async_persistent", "0",PHP_INI_SYSTEM, + OnUpdateInt, allow_async_persistent, php_pgsql_globals, +pgsql_globals) PHP_INI_END() /* }}} */ @@ -1962,7 +1975,291 @@ } /* }}} */ #endif + +/* Following functions are for asyncronous query + Note: It is PHP programmers' responsibilty making sure getting consistent result + when async query function is used for persistent connection. +*/ + +#define PHP_PG_ASYNC_ISNONBLOCKING 1 +#define PHP_PG_ASYNC_CONSUMEINPUT 2 +#define PHP_PG_ASYNC_ISBUSY 3 +#define PHP_PG_ASYNC_FLUSH 4 +#define PHP_PG_ASYNC_REQUESTCANCEL 5 + +void php_pgsql_async_query(INTERNAL_FUNCTION_PARAMETERS, int type) +{ + zval **pgsql_link = NULL; + int id = -1; + PGconn *pgsql; + + switch(ZEND_NUM_ARGS()) { + case 0: + id = PGG(default_link); + CHECK_DEFAULT_LINK(id); + break; + case 1: + if (zend_get_parameters_ex(1, &pgsql_link)==FAILURE) { + RETURN_FALSE; + } + break; + default: + WRONG_PARAM_COUNT; + break; + } + + ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL link", +le_link, le_plink); + + switch(type) { + case PHP_PG_ASYNC_ISNONBLOCKING: + Z_LVAL_P(return_value) = PQisnonblocking(pgsql); + Z_TYPE_P(return_value) = IS_LONG; + break; + case PHP_PG_ASYNC_CONSUMEINPUT: + Z_LVAL_P(return_value) = PQconsumeInput(pgsql); + Z_TYPE_P(return_value) = IS_LONG; + break; + case PHP_PG_ASYNC_ISBUSY: + Z_LVAL_P(return_value) = PQisBusy(pgsql); + Z_TYPE_P(return_value) = IS_LONG; + break; + case PHP_PG_ASYNC_FLUSH: + Z_LVAL_P(return_value) = PQflush(pgsql); + Z_TYPE_P(return_value) = IS_LONG; + case PHP_PG_ASYNC_REQUESTCANCEL: + Z_LVAL_P(return_value) = PQrequestCancel(pgsql); + Z_TYPE_P(return_value) = IS_LONG; + default: + php_error(E_ERROR,"Pgsql module error. Report this error"); + break; + } + convert_to_boolean_ex(&return_value); +} + +/* {{{ proto bool pg_consumeinput([resource connection]) + Consume input */ +PHP_FUNCTION(pg_consumeinput) +{ + php_pgsql_async_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, +PHP_PG_ASYNC_CONSUMEINPUT); +} +/* }}} */ + +/* {{{ proto bool pg_requestcancel([resource connection]) + Cancel request */ +PHP_FUNCTION(pg_requestcancel) +{ + php_pgsql_async_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, +PHP_PG_ASYNC_REQUESTCANCEL); +} +/* }}} */ + +/* {{{ proto query bool pg_isbusy([resource connection]) + Get connection is busy or not */ +PHP_FUNCTION(pg_isbusy) +{ + php_pgsql_async_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_ASYNC_ISBUSY); +} +/* }}} */ + +/* {{{ proto query bool pg_flush([resource connection]) + Try to flush any data in backend */ +PHP_FUNCTION(pg_flush) +{ + php_pgsql_async_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_ASYNC_FLUSH); +} +/* }}} */ + +/* {{{ proto bool pg_isnonblocking([resource connection]) + Set block mode */ +PHP_FUNCTION(pg_isnonblocking) +{ + php_pgsql_async_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, +PHP_PG_ASYNC_ISNONBLOCKING); +} + +/* {{{ proto bool pg_setnonblocking([resource connection], bool flag) + Set blocking mode */ +PHP_FUNCTION(pg_setnonblocking) +{ + zval **pgsql_link = NULL; + zval **flag; + int id = -1; + PGconn *pgsql; + + switch(ZEND_NUM_ARGS()) { + case 1: + if (zend_get_parameters_ex(1, &flag)==FAILURE) { + RETURN_FALSE; + } + id = PGG(default_link); + CHECK_DEFAULT_LINK(id); + break; + case 2: + if (zend_get_parameters_ex(2, &pgsql_link, &flag)==FAILURE) { + RETURN_FALSE; + } + convert_to_boolean_ex(flag); + break; + default: + WRONG_PARAM_COUNT; + break; + } + + ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL link", le_link, +le_plink); + + convert_to_long_ex(flag); + if (PQsetnonblocking(pgsql, Z_LVAL_PP(flag))) { + RETURN_FALSE; + } + RETURN_TRUE; +} + +/* {{{ proto bool pg_sendquery([resource connection], string qeury) + Send asynchronous query */ +PHP_FUNCTION(pg_sendquery) +{ + zval **query, **pgsql_link = NULL; + int id = -1; + PGconn *pgsql; + + switch(ZEND_NUM_ARGS()) { + case 1: + if (zend_get_parameters_ex(1, &query)==FAILURE) { + RETURN_FALSE; + } + id = PGG(default_link); + CHECK_DEFAULT_LINK(id); + break; + case 2: + if (zend_get_parameters_ex(2, &pgsql_link, &query)==FAILURE) { + RETURN_FALSE; + } + break; + default: + WRONG_PARAM_COUNT; + break; + } + ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL link", +le_link, le_plink); + + convert_to_string_ex(query); + if (!PQsendQuery(pgsql, Z_STRVAL_PP(query))) { + RETURN_FALSE; + } + RETURN_TRUE; +} +/* }}} */ + + +/* {{{ proto query resouce pg_getresult([resource connection]) + Get asynchronous query result */ +PHP_FUNCTION(pg_getresult) +{ + zval **pgsql_link = NULL; + int id = -1; + PGconn *pgsql; + PGresult *pgsql_result; + pgsql_result_handle *pg_result; + + switch(ZEND_NUM_ARGS()) { + case 0: + id = PGG(default_link); + CHECK_DEFAULT_LINK(id); + break; + case 1: + if (zend_get_parameters_ex(1, &pgsql_link)==FAILURE) { + RETURN_FALSE; + } + break; + default: + WRONG_PARAM_COUNT; + break; + } + + ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL link", +le_link, le_plink); + + pgsql_result = PQgetResult(pgsql); + + if (pgsql_result) { + pg_result = (pgsql_result_handle *) +emalloc(sizeof(pgsql_result_handle)); + pg_result->conn = pgsql; + pg_result->result = pgsql_result; + pg_result->row = -1; + ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result); + } else { + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ proto int pg_socket([resource connection]) + Returns backend's soket number */ +PHP_FUNCTION(pg_socket) +{ + zval **pgsql_link = NULL; + int id = -1; + int sock = -1; + PGconn *pgsql; + + switch(ZEND_NUM_ARGS()) { + case 0: + id = PGG(default_link); + CHECK_DEFAULT_LINK(id); + break; + case 1: + if (zend_get_parameters_ex(1, &pgsql_link)==FAILURE) { + RETURN_FALSE; + } + break; + default: + WRONG_PARAM_COUNT; + break; + } + + ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL link", +le_link, le_plink); + + sock = PQsocket(pgsql); + if (sock == -1) { + RETURN_FALSE; + } + Z_LVAL_P(return_value) = sock; + Z_TYPE_P(return_value) = IS_LONG; +} +/* }}} */ + +/* {{{ proto string pg_notify pg_notifies([resource connection]) + Get notification */ +PHP_FUNCTION(pg_notifies) +{ + zval **pgsql_link = NULL; + int id = -1; + PGconn *pgsql; + PGnotify *notice; + + switch(ZEND_NUM_ARGS()) { + case 0: + id = PGG(default_link); + CHECK_DEFAULT_LINK(id); + break; + case 1: + if (zend_get_parameters_ex(1, &pgsql_link)==FAILURE) { + RETURN_FALSE; + } + break; + default: + WRONG_PARAM_COUNT; + break; + } + + ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL link", +le_link, le_plink); + + notice = PQnotifies(pgsql); + if (!notice) { + RETURN_FALSE; + } + Z_STRLEN_P(return_value) = strlen(notice->relname); + Z_STRVAL_P(return_value) = (char *)estrndup(notice->relname, +Z_STRLEN_P(return_value)); + Z_TYPE_P(return_value) = IS_STRING; +} + #endif /* Index: php_pgsql.h =================================================================== RCS file: /repository/php4/ext/pgsql/php_pgsql.h,v retrieving revision 1.33 diff -u -r1.33 php_pgsql.h --- php_pgsql.h 26 Sep 2001 21:44:48 -0000 1.33 +++ php_pgsql.h 3 Nov 2001 18:19:21 -0000 @@ -94,6 +94,18 @@ PHP_FUNCTION(pg_client_encoding); PHP_FUNCTION(pg_set_client_encoding); #endif +/* Asynchronus Query Interfase + Note: These are not thread safe. Separate connection must be used if nessesary */ +PHP_FUNCTION(pg_sendquery); +PHP_FUNCTION(pg_setnonblocking); +PHP_FUNCTION(pg_isnonblocking); +PHP_FUNCTION(pg_getresult); +PHP_FUNCTION(pg_isbusy); +PHP_FUNCTION(pg_flush); +PHP_FUNCTION(pg_socket); +PHP_FUNCTION(pg_consumeinput); +PHP_FUNCTION(pg_requestcancel); +PHP_FUNCTION(pg_notifies); void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS,int persistent); int php_pgsql_get_default_link(INTERNAL_FUNCTION_PARAMETERS); @@ -103,7 +115,6 @@ void php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type); void php_pgsql_data_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type); - typedef struct pgLofp { PGconn *conn; int lofd; @@ -120,6 +131,7 @@ long num_links,num_persistent; long max_links,max_persistent; long allow_persistent; + long allow_async_persistent; int le_lofp,le_string; int ignore_notices; char *last_notice;
-- PHP Development Mailing List <http://www.php.net/> To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] To contact the list administrators, e-mail: [EMAIL PROTECTED]