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]

Reply via email to