[PHP-dev 125] Re: [patch] pgsql async query

Yasuo Ohgaki php-dev@php.gr.jp
Sun, 25 Nov 2001 19:03:06 +0900


This is a multi-part message in MIME format.

------=_NextPart_000_00AD_01C175E3.D0EC2F10
Content-Type: text/plain;
	charset="iso-2022-jp"
Content-Transfer-Encoding: 7bit

A few changes,

 - pg_reset() returns boolean value now
 - added more cleanup for leftover

Comments are welcome.

PS: If you have problem with attachment, please let me know.

--
Yasuo Ohgaki

------=_NextPart_000_00AD_01C175E3.D0EC2F10
Content-Type: application/octet-stream;
	name="pgsql_async.diff"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="pgsql_async.diff"

Index: pgsql.c=0A=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
RCS file: /repository/php4/ext/pgsql/pgsql.c,v=0A=
retrieving revision 1.130=0A=
diff -u -r1.130 pgsql.c=0A=
--- pgsql.c	11 Oct 2001 23:33:40 -0000	1.130=0A=
+++ pgsql.c	25 Nov 2001 09:35:22 -0000=0A=
@@ -94,6 +94,12 @@=0A=
 	PHP_FALIAS(pg_clientencoding,		pg_client_encoding,			NULL)=0A=
 	PHP_FALIAS(pg_setclientencoding,	pg_set_client_encoding,	NULL)=0A=
 #endif=0A=
+	PHP_FE(pg_reset,				 NULL)=0A=
+	PHP_FE(pg_status,				 NULL)=0A=
+	PHP_FE(pg_send_query,			 NULL)=0A=
+	PHP_FE(pg_request_cancel,		 NULL)=0A=
+	PHP_FE(pg_get_result,			 NULL)=0A=
+	PHP_FE(pg_is_busy,				 NULL)=0A=
 	{NULL, NULL, NULL}=0A=
 };=0A=
 /* }}} */=0A=
@@ -147,7 +153,17 @@=0A=
 static void _close_pgsql_link(zend_rsrc_list_entry *rsrc TSRMLS_DC)=0A=
 {=0A=
 	PGconn *link =3D (PGconn *)rsrc->ptr;=0A=
+	PGresult *res;=0A=
 =0A=
+	PQsetnonblocking(link,1);=0A=
+	if (PQisBusy(link)) {=0A=
+		if (!PQrequestCancel(link)) {=0A=
+			php_error(E_WARNING,"PostgreSQL: failed to cancel qeury. %s", =
PQerrorMessage(link));=0A=
+		}=0A=
+	}=0A=
+	while ((res =3D PQgetResult(link))) {=0A=
+		PQclear(res);=0A=
+	}=0A=
 	PQfinish(link);=0A=
 	PGG(num_links)--;=0A=
 }=0A=
@@ -158,7 +174,17 @@=0A=
 static void _close_pgsql_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC)=0A=
 {=0A=
 	PGconn *link =3D (PGconn *)rsrc->ptr;=0A=
+	PGresult *res;=0A=
 =0A=
+	PQsetnonblocking(link,1);=0A=
+	if (PQisBusy(link)) {=0A=
+		if (!PQrequestCancel(link)) {=0A=
+			php_error(E_WARNING,"PostgreSQL: failed to cancel qeury. %s", =
PQerrorMessage(link));=0A=
+		}=0A=
+	}=0A=
+	while ((res =3D PQgetResult(link))) {=0A=
+		PQclear(res);=0A=
+	}=0A=
 	PQfinish(link);=0A=
 	PGG(num_persistent)--;=0A=
 	PGG(num_links)--;=0A=
@@ -187,12 +213,22 @@=0A=
 static int _rollback_transactions(zend_rsrc_list_entry *rsrc TSRMLS_DC)=0A=
 {=0A=
 	PGconn *link;=0A=
+	PGresult *res;=0A=
 =0A=
 	if (Z_TYPE_P(rsrc) !=3D le_plink) =0A=
 		return 0;=0A=
 =0A=
 	link =3D (PGconn *) rsrc->ptr;=0A=
 	=0A=
+	PQsetnonblocking(link,1);=0A=
+	if (PQisBusy(link)) {=0A=
+		if (!PQrequestCancel(link)) {=0A=
+			php_error(E_WARNING,"PostgreSQL: failed to cancel qeury. %s", =
PQerrorMessage(link));=0A=
+		}=0A=
+	}=0A=
+	while ((res =3D PQgetResult(link))) {=0A=
+		PQclear(res);=0A=
+	}=0A=
 	PGG(ignore_notices) =3D 1;=0A=
 	PQexec(link,"BEGIN;ROLLBACK;");=0A=
 	PGG(ignore_notices) =3D 0;=0A=
@@ -262,6 +298,9 @@=0A=
 	REGISTER_LONG_CONSTANT("PGSQL_NUM", PGSQL_NUM, CONST_CS | =
CONST_PERSISTENT);=0A=
 	REGISTER_LONG_CONSTANT("PGSQL_BOTH", PGSQL_BOTH, CONST_CS | =
CONST_PERSISTENT);=0A=
 =0A=
+	REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_BAD", CONNECTION_BAD, =
CONST_CS | CONST_PERSISTENT);=0A=
+	REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_OK", CONNECTION_OK, CONST_CS =
| CONST_PERSISTENT);=0A=
+=0A=
 	return SUCCESS;=0A=
 }=0A=
 /* }}} */=0A=
@@ -717,11 +756,12 @@=0A=
 {=0A=
 	zval **query, **pgsql_link =3D NULL;=0A=
 	int id =3D -1;=0A=
+	int leftover =3D 0;=0A=
 	PGconn *pgsql;=0A=
 	PGresult *pgsql_result;=0A=
 	ExecStatusType status;=0A=
 	pgsql_result_handle *pg_result;=0A=
-=0A=
+	=0A=
 	switch(ZEND_NUM_ARGS()) {=0A=
 		case 1:=0A=
 			if (zend_get_parameters_ex(1, &query)=3D=3DFAILURE) {=0A=
@@ -743,6 +783,17 @@=0A=
 	ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL =
link", le_link, le_plink);=0A=
 =0A=
 	convert_to_string_ex(query);=0A=
+	if (PQisBusy(pgsql)) {=0A=
+		php_error(E_NOTICE,"PostgreSQL: Cannot execute query while executing =
async query.");=0A=
+		RETURN_FALSE;=0A=
+	}=0A=
+	while ((pgsql_result =3D PQgetResult(pgsql))) {=0A=
+		PQclear(pgsql_result);=0A=
+		leftover =3D 1;=0A=
+	}=0A=
+	if (leftover) {=0A=
+		php_error(E_WARNING,"PostgreSQL: There are results on this =
connection. Use pg_get_result() to get results");=0A=
+	}=0A=
 	pgsql_result =3D PQexec(pgsql, Z_STRVAL_PP(query));=0A=
 	=0A=
 	if (pgsql_result) {=0A=
@@ -751,7 +802,6 @@=0A=
 		status =3D (ExecStatusType) PQstatus(pgsql);=0A=
 	}=0A=
 	=0A=
-	=0A=
 	switch (status) {=0A=
 		case PGRES_EMPTY_QUERY:=0A=
 		case PGRES_BAD_RESPONSE:=0A=
@@ -1962,7 +2012,240 @@=0A=
 }=0A=
 /* }}} */=0A=
 #endif=0A=
+=0A=
+=0A=
+/* {{{ proto long pg_status(resource conn)=0A=
+   Get connection status */=0A=
+PHP_FUNCTION(pg_status)=0A=
+{=0A=
+	zval **pgsql_link =3D NULL;=0A=
+	int id =3D -1;=0A=
+	PGconn *pgsql;=0A=
+=0A=
+	switch(ZEND_NUM_ARGS()) {=0A=
+		case 0:=0A=
+			id =3D PGG(default_link);=0A=
+			CHECK_DEFAULT_LINK(id);=0A=
+			break;=0A=
+		case 1:=0A=
+			if (zend_get_parameters_ex(1, &pgsql_link)=3D=3DFAILURE) {=0A=
+				RETURN_FALSE;=0A=
+			}=0A=
+			break;=0A=
+		default:=0A=
+			WRONG_PARAM_COUNT;=0A=
+			break;=0A=
+	}=0A=
+=0A=
+	ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL =
link", le_link, le_plink);=0A=
+	Z_LVAL_P(return_value) =3D PQstatus(pgsql);=0A=
+	Z_TYPE_P(return_value) =3D IS_LONG;=0A=
+}=0A=
+=0A=
+/* }}} */=0A=
+=0A=
+/* {{{ proto bool pg_reset(resource conn)=0A=
+   Reset connection */=0A=
+PHP_FUNCTION(pg_reset)=0A=
+{=0A=
+	zval **pgsql_link =3D NULL;=0A=
+	int id =3D -1;=0A=
+	PGconn *pgsql;=0A=
+=0A=
+	switch(ZEND_NUM_ARGS()) {=0A=
+		case 0:=0A=
+			id =3D PGG(default_link);=0A=
+			CHECK_DEFAULT_LINK(id);=0A=
+			break;=0A=
+		case 1:=0A=
+			if (zend_get_parameters_ex(1, &pgsql_link)=3D=3DFAILURE) {=0A=
+				RETURN_FALSE;=0A=
+			}=0A=
+			break;=0A=
+		default:=0A=
+			WRONG_PARAM_COUNT;=0A=
+			break;=0A=
+	}=0A=
+	ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL =
link", le_link, le_plink);=0A=
+	PQreset(pgsql);=0A=
+	if (PQstatus(pgsql) =3D=3D CONNECTION_BAD) {=0A=
+		RETURN_FALSE;=0A=
+	}=0A=
+	RETURN_TRUE;=0A=
+}=0A=
+=0A=
+/* }}} */=0A=
+=0A=
+/* Following functions are for asyncronous query=0A=
+ * Report bugs to yasuo_ohgaki@yahoo.com=0A=
+ */ =0A=
+#define PHP_PG_ASYNC_IS_BUSY		1=0A=
+#define PHP_PG_ASYNC_REQUEST_CANCEL 2=0A=
+=0A=
+/* {{{ php_pgsql_do_async=0A=
+ */=0A=
+void php_pgsql_do_async(INTERNAL_FUNCTION_PARAMETERS, int entry_type) =0A=
+{=0A=
+	zval **pgsql_link =3D NULL;=0A=
+	int id =3D -1;=0A=
+	PGconn *pgsql;=0A=
+	PGresult *pgsql_result;=0A=
+=0A=
+	switch(ZEND_NUM_ARGS()) {=0A=
+		case 0:=0A=
+			id =3D PGG(default_link);=0A=
+			CHECK_DEFAULT_LINK(id);=0A=
+			break;=0A=
+		case 1:=0A=
+			if (zend_get_parameters_ex(1, &pgsql_link)=3D=3DFAILURE) {=0A=
+				RETURN_FALSE;=0A=
+			}=0A=
+			break;=0A=
+		default:=0A=
+			WRONG_PARAM_COUNT;=0A=
+			break;=0A=
+	}=0A=
+=0A=
+	ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL =
link", le_link, le_plink);=0A=
+=0A=
+	switch(entry_type) {=0A=
+		case PHP_PG_ASYNC_IS_BUSY:=0A=
+			PQconsumeInput(pgsql);=0A=
+			Z_LVAL_P(return_value) =3D PQisBusy(pgsql);=0A=
+			Z_TYPE_P(return_value) =3D IS_LONG;=0A=
+			break;=0A=
+		case PHP_PG_ASYNC_REQUEST_CANCEL:=0A=
+			Z_LVAL_P(return_value) =3D PQrequestCancel(pgsql);=0A=
+			Z_TYPE_P(return_value) =3D IS_LONG;=0A=
+			while ((pgsql_result =3D PQgetResult(pgsql))) {=0A=
+				PQclear(pgsql_result);=0A=
+			}=0A=
+			break;=0A=
+		default:=0A=
+			php_error(E_ERROR,"Pgsql module error. Report this error");=0A=
+			break;=0A=
+	}=0A=
+	convert_to_boolean_ex(&return_value);=0A=
+}=0A=
+/* }}} */=0A=
+=0A=
+/* {{{ proto bool pg_async_request_cancel([resource connection])=0A=
+   Cancel request */=0A=
+PHP_FUNCTION(pg_request_cancel)=0A=
+{=0A=
+	php_pgsql_do_async(INTERNAL_FUNCTION_PARAM_PASSTHRU, =
PHP_PG_ASYNC_REQUEST_CANCEL);=0A=
+}=0A=
+/* }}} */=0A=
+=0A=
+/* {{{ proto query bool pg_isbusy([resource connection])=0A=
+   Get connection is busy or not */=0A=
+PHP_FUNCTION(pg_is_busy)=0A=
+{=0A=
+	php_pgsql_do_async(INTERNAL_FUNCTION_PARAM_PASSTHRU, =
PHP_PG_ASYNC_IS_BUSY);=0A=
+}=0A=
+/* }}} */=0A=
+=0A=
+/* {{{ proto bool pg_async_exec([resource connection], string qeury)=0A=
+   Send asynchronous query */=0A=
+PHP_FUNCTION(pg_send_query)=0A=
+{=0A=
+	zval **query, **pgsql_link =3D NULL;=0A=
+	int id =3D -1;=0A=
+	PGconn *pgsql;=0A=
+	PGresult *res;=0A=
+	int leftover =3D 0;=0A=
+=0A=
+	switch(ZEND_NUM_ARGS()) {=0A=
+		case 1:=0A=
+			if (zend_get_parameters_ex(1, &query)=3D=3DFAILURE) {=0A=
+				RETURN_FALSE;=0A=
+			}=0A=
+			id =3D PGG(default_link);=0A=
+			CHECK_DEFAULT_LINK(id);=0A=
+			break;=0A=
+		case 2:=0A=
+			if (zend_get_parameters_ex(2, &pgsql_link, &query)=3D=3DFAILURE) {=0A=
+				RETURN_FALSE;=0A=
+			}=0A=
+			break;=0A=
+		default:=0A=
+			WRONG_PARAM_COUNT;=0A=
+			break;=0A=
+	}=0A=
 	=0A=
+	ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL =
link", le_link, le_plink);=0A=
+=0A=
+	convert_to_string_ex(query);=0A=
+	if (PQsetnonblocking(pgsql, 1)) {=0A=
+		php_error(E_NOTICE,"PostgreSQL: Cannot set connection to nonblocking =
mode in pg_send_query()");=0A=
+	}=0A=
+	if (PQisBusy(pgsql)) {=0A=
+		php_error(E_WARNING,"PostgreSQL: Cannot send multiple query using =
pg_send_query()");=0A=
+		RETURN_FALSE;=0A=
+	}=0A=
+	while ((res =3D PQgetResult(pgsql))) {=0A=
+		PQclear(res);=0A=
+		leftover =3D 1;=0A=
+	}=0A=
+	if (leftover) {=0A=
+		php_error(E_NOTICE,"PostgreSQL: There are results on this connection. =
Call pg_get_result() until it returns false");=0A=
+	}=0A=
+	if (!PQsendQuery(pgsql, Z_STRVAL_PP(query))) {=0A=
+		RETURN_FALSE;=0A=
+	}=0A=
+	if (PQsetnonblocking(pgsql, 0)) {=0A=
+		php_error(E_NOTICE,"PostgreSQL: Cannot set connection to blocking =
mode in pg_send_query()");=0A=
+	}=0A=
+	RETURN_TRUE;=0A=
+}=0A=
+/* }}} */=0A=
+=0A=
+=0A=
+/* {{{ proto query resouce pg_arync_result([resource connection])=0A=
+   Get asynchronous query result */=0A=
+PHP_FUNCTION(pg_get_result)=0A=
+{=0A=
+	zval **pgsql_link =3D NULL;=0A=
+	int id =3D -1;=0A=
+	PGconn *pgsql;=0A=
+	PGresult *pgsql_result;=0A=
+	pgsql_result_handle *pg_result;=0A=
+=0A=
+	switch(ZEND_NUM_ARGS()) {=0A=
+		case 0:=0A=
+			id =3D PGG(default_link);=0A=
+			CHECK_DEFAULT_LINK(id);=0A=
+			break;=0A=
+		case 1:=0A=
+			if (zend_get_parameters_ex(1, &pgsql_link)=3D=3DFAILURE) {=0A=
+				RETURN_FALSE;=0A=
+			}=0A=
+			break;=0A=
+		default:=0A=
+			WRONG_PARAM_COUNT;=0A=
+			break;=0A=
+	}=0A=
+=0A=
+	ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL =
link", le_link, le_plink);=0A=
+	if (PQsetnonblocking(pgsql, 1)) {=0A=
+		php_error(E_NOTICE,"PostgreSQL: Cannot set connection to nonblocking =
mode in pg_get_result()");=0A=
+	}=0A=
+	pgsql_result =3D PQgetResult(pgsql);=0A=
+	if (!pgsql_result) {=0A=
+		/* no result */=0A=
+		RETURN_FALSE;=0A=
+	}=0A=
+	if (PQsetnonblocking(pgsql, 0)) {=0A=
+		php_error(E_NOTICE,"PostgreSQL: Cannot set connection to blocking =
mode in pg_get_result()");=0A=
+	}=0A=
+	pg_result =3D (pgsql_result_handle *) =
emalloc(sizeof(pgsql_result_handle));=0A=
+	pg_result->conn =3D pgsql;=0A=
+	pg_result->result =3D pgsql_result;=0A=
+	pg_result->row =3D -1;=0A=
+	ZEND_REGISTER_RESOURCE(return_value, pg_result, le_result);=0A=
+}=0A=
+/* }}} */=0A=
+=0A=
 #endif=0A=
 =0A=
 /*=0A=
Index: php_pgsql.h=0A=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
RCS file: /repository/php4/ext/pgsql/php_pgsql.h,v=0A=
retrieving revision 1.33=0A=
diff -u -r1.33 php_pgsql.h=0A=
--- php_pgsql.h	26 Sep 2001 21:44:48 -0000	1.33=0A=
+++ php_pgsql.h	25 Nov 2001 09:35:23 -0000=0A=
@@ -94,6 +94,12 @@=0A=
 PHP_FUNCTION(pg_client_encoding);=0A=
 PHP_FUNCTION(pg_set_client_encoding);=0A=
 #endif=0A=
+PHP_FUNCTION(pg_reset);=0A=
+PHP_FUNCTION(pg_status);=0A=
+PHP_FUNCTION(pg_send_query);=0A=
+PHP_FUNCTION(pg_request_cancel);=0A=
+PHP_FUNCTION(pg_get_result);=0A=
+PHP_FUNCTION(pg_is_busy);=0A=
 =0A=
 void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS,int persistent);=0A=
 int php_pgsql_get_default_link(INTERNAL_FUNCTION_PARAMETERS);=0A=
@@ -102,7 +108,7 @@=0A=
 char *get_field_name(PGconn *pgsql, Oid oid, HashTable *list);=0A=
 void php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAMETERS, int =
entry_type);=0A=
 void php_pgsql_data_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type);=0A=
-=0A=
+void php_pgsql_do_async(INTERNAL_FUNCTION_PARAMETERS,int entry_type);=0A=
 =0A=
 typedef struct pgLofp {=0A=
         PGconn *conn;=0A=

------=_NextPart_000_00AD_01C175E3.D0EC2F10--