Yasuo Ohgaki wrote:

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

It seems there is problem with my mail client (or news.php.net?)
This mail is for those who get the patch as inline...

After this patch is committed (by someone hopefully). I'll send
another patch that get rid of zend_get_parameters() and make pgsql
module use zend_parse_parameters(), if nobody objects.

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

Reply via email to