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]