Added async query functions

This commit is contained in:
Yasuo Ohgaki 2001-12-10 04:02:08 +00:00
parent b11d1eb440
commit db8bb9f23c
2 changed files with 294 additions and 3 deletions

View file

@ -94,6 +94,12 @@ function_entry pgsql_functions[] = {
PHP_FALIAS(pg_clientencoding, pg_client_encoding, NULL) PHP_FALIAS(pg_clientencoding, pg_client_encoding, NULL)
PHP_FALIAS(pg_setclientencoding, pg_set_client_encoding, NULL) PHP_FALIAS(pg_setclientencoding, pg_set_client_encoding, NULL)
#endif #endif
PHP_FE(pg_reset, NULL)
PHP_FE(pg_status, NULL)
PHP_FE(pg_send_query, NULL)
PHP_FE(pg_request_cancel, NULL)
PHP_FE(pg_get_result, NULL)
PHP_FE(pg_is_busy, NULL)
{NULL, NULL, NULL} {NULL, NULL, NULL}
}; };
/* }}} */ /* }}} */
@ -147,7 +153,17 @@ static void php_pgsql_set_default_link(int id)
static void _close_pgsql_link(zend_rsrc_list_entry *rsrc TSRMLS_DC) static void _close_pgsql_link(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{ {
PGconn *link = (PGconn *)rsrc->ptr; PGconn *link = (PGconn *)rsrc->ptr;
PGresult *res;
PQsetnonblocking(link,1);
if (PQisBusy(link)) {
if (!PQrequestCancel(link)) {
php_error(E_WARNING,"PostgreSQL: failed to cancel qeury. %s", PQerrorMessage(link));
}
}
while ((res = PQgetResult(link))) {
PQclear(res);
}
PQfinish(link); PQfinish(link);
PGG(num_links)--; PGG(num_links)--;
} }
@ -158,7 +174,17 @@ static void _close_pgsql_link(zend_rsrc_list_entry *rsrc TSRMLS_DC)
static void _close_pgsql_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC) static void _close_pgsql_plink(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{ {
PGconn *link = (PGconn *)rsrc->ptr; PGconn *link = (PGconn *)rsrc->ptr;
PGresult *res;
PQsetnonblocking(link,1);
if (PQisBusy(link)) {
if (!PQrequestCancel(link)) {
php_error(E_WARNING,"PostgreSQL: failed to cancel qeury. %s", PQerrorMessage(link));
}
}
while ((res = PQgetResult(link))) {
PQclear(res);
}
PQfinish(link); PQfinish(link);
PGG(num_persistent)--; PGG(num_persistent)--;
PGG(num_links)--; PGG(num_links)--;
@ -187,12 +213,22 @@ static void _notice_handler(void *arg, const char *message)
static int _rollback_transactions(zend_rsrc_list_entry *rsrc TSRMLS_DC) static int _rollback_transactions(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{ {
PGconn *link; PGconn *link;
PGresult *res;
if (Z_TYPE_P(rsrc) != le_plink) if (Z_TYPE_P(rsrc) != le_plink)
return 0; return 0;
link = (PGconn *) rsrc->ptr; link = (PGconn *) rsrc->ptr;
PQsetnonblocking(link,1);
if (PQisBusy(link)) {
if (!PQrequestCancel(link)) {
php_error(E_WARNING,"PostgreSQL: failed to cancel qeury. %s", PQerrorMessage(link));
}
}
while ((res = PQgetResult(link))) {
PQclear(res);
}
PGG(ignore_notices) = 1; PGG(ignore_notices) = 1;
PQexec(link,"BEGIN;ROLLBACK;"); PQexec(link,"BEGIN;ROLLBACK;");
PGG(ignore_notices) = 0; PGG(ignore_notices) = 0;
@ -262,6 +298,9 @@ PHP_MINIT_FUNCTION(pgsql)
REGISTER_LONG_CONSTANT("PGSQL_NUM", PGSQL_NUM, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PGSQL_NUM", PGSQL_NUM, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PGSQL_BOTH", PGSQL_BOTH, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("PGSQL_BOTH", PGSQL_BOTH, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_BAD", CONNECTION_BAD, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PGSQL_CONNECTION_OK", CONNECTION_OK, CONST_CS | CONST_PERSISTENT);
return SUCCESS; return SUCCESS;
} }
/* }}} */ /* }}} */
@ -717,11 +756,12 @@ PHP_FUNCTION(pg_exec)
{ {
zval **query, **pgsql_link = NULL; zval **query, **pgsql_link = NULL;
int id = -1; int id = -1;
int leftover = 0;
PGconn *pgsql; PGconn *pgsql;
PGresult *pgsql_result; PGresult *pgsql_result;
ExecStatusType status; ExecStatusType status;
pgsql_result_handle *pg_result; pgsql_result_handle *pg_result;
switch(ZEND_NUM_ARGS()) { switch(ZEND_NUM_ARGS()) {
case 1: case 1:
if (zend_get_parameters_ex(1, &query)==FAILURE) { if (zend_get_parameters_ex(1, &query)==FAILURE) {
@ -743,6 +783,17 @@ PHP_FUNCTION(pg_exec)
ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL link", le_link, le_plink); ZEND_FETCH_RESOURCE2(pgsql, PGconn *, pgsql_link, id, "PostgreSQL link", le_link, le_plink);
convert_to_string_ex(query); convert_to_string_ex(query);
if (PQisBusy(pgsql)) {
php_error(E_NOTICE,"PostgreSQL: Cannot execute query while executing async query.");
RETURN_FALSE;
}
while ((pgsql_result = PQgetResult(pgsql))) {
PQclear(pgsql_result);
leftover = 1;
}
if (leftover) {
php_error(E_WARNING,"PostgreSQL: There are results on this connection. Use pg_get_result() to get results");
}
pgsql_result = PQexec(pgsql, Z_STRVAL_PP(query)); pgsql_result = PQexec(pgsql, Z_STRVAL_PP(query));
if (pgsql_result) { if (pgsql_result) {
@ -751,7 +802,6 @@ PHP_FUNCTION(pg_exec)
status = (ExecStatusType) PQstatus(pgsql); status = (ExecStatusType) PQstatus(pgsql);
} }
switch (status) { switch (status) {
case PGRES_EMPTY_QUERY: case PGRES_EMPTY_QUERY:
case PGRES_BAD_RESPONSE: case PGRES_BAD_RESPONSE:
@ -816,6 +866,8 @@ PHP_FUNCTION(pg_end_copy)
} }
/* }}} */ /* }}} */
#define COPYBUFSIZ 8192
/* {{{ proto int pg_put_line([int connection,] string query) /* {{{ proto int pg_put_line([int connection,] string query)
Send null-terminated string to backend server*/ Send null-terminated string to backend server*/
PHP_FUNCTION(pg_put_line) PHP_FUNCTION(pg_put_line)
@ -1962,7 +2014,240 @@ PHP_FUNCTION(pg_client_encoding)
} }
/* }}} */ /* }}} */
#endif #endif
/* {{{ proto long pg_status(resource conn)
Get connection status */
PHP_FUNCTION(pg_status)
{
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);
Z_LVAL_P(return_value) = PQstatus(pgsql);
Z_TYPE_P(return_value) = IS_LONG;
}
/* }}} */
/* {{{ proto bool pg_reset(resource conn)
Reset connection */
PHP_FUNCTION(pg_reset)
{
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);
PQreset(pgsql);
if (PQstatus(pgsql) == CONNECTION_BAD) {
RETURN_FALSE;
}
RETURN_TRUE;
}
/* }}} */
/* Following functions are for asyncronous query
* Report bugs to yasuo_ohgaki@yahoo.com
*/
#define PHP_PG_ASYNC_IS_BUSY 1
#define PHP_PG_ASYNC_REQUEST_CANCEL 2
/* {{{ php_pgsql_do_async
*/
void php_pgsql_do_async(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
{
zval **pgsql_link = NULL;
int id = -1;
PGconn *pgsql;
PGresult *pgsql_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);
switch(entry_type) {
case PHP_PG_ASYNC_IS_BUSY:
PQconsumeInput(pgsql);
Z_LVAL_P(return_value) = PQisBusy(pgsql);
Z_TYPE_P(return_value) = IS_LONG;
break;
case PHP_PG_ASYNC_REQUEST_CANCEL:
Z_LVAL_P(return_value) = PQrequestCancel(pgsql);
Z_TYPE_P(return_value) = IS_LONG;
while ((pgsql_result = PQgetResult(pgsql))) {
PQclear(pgsql_result);
}
break;
default:
php_error(E_ERROR,"Pgsql module error. Report this error");
break;
}
convert_to_boolean_ex(&return_value);
}
/* }}} */
/* {{{ proto bool pg_async_request_cancel([resource connection])
Cancel request */
PHP_FUNCTION(pg_request_cancel)
{
php_pgsql_do_async(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_ASYNC_REQUEST_CANCEL);
}
/* }}} */
/* {{{ proto query bool pg_isbusy([resource connection])
Get connection is busy or not */
PHP_FUNCTION(pg_is_busy)
{
php_pgsql_do_async(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_PG_ASYNC_IS_BUSY);
}
/* }}} */
/* {{{ proto bool pg_async_exec([resource connection], string qeury)
Send asynchronous query */
PHP_FUNCTION(pg_send_query)
{
zval **query, **pgsql_link = NULL;
int id = -1;
PGconn *pgsql;
PGresult *res;
int leftover = 0;
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 (PQsetnonblocking(pgsql, 1)) {
php_error(E_NOTICE,"PostgreSQL: Cannot set connection to nonblocking mode in pg_send_query()");
}
if (PQisBusy(pgsql)) {
php_error(E_WARNING,"PostgreSQL: Cannot send multiple query using pg_send_query()");
RETURN_FALSE;
}
while ((res = PQgetResult(pgsql))) {
PQclear(res);
leftover = 1;
}
if (leftover) {
php_error(E_NOTICE,"PostgreSQL: There are results on this connection. Call pg_get_result() until it returns false");
}
if (!PQsendQuery(pgsql, Z_STRVAL_PP(query))) {
RETURN_FALSE;
}
if (PQsetnonblocking(pgsql, 0)) {
php_error(E_NOTICE,"PostgreSQL: Cannot set connection to blocking mode in pg_send_query()");
}
RETURN_TRUE;
}
/* }}} */
/* {{{ proto query resouce pg_arync_result([resource connection])
Get asynchronous query result */
PHP_FUNCTION(pg_get_result)
{
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);
if (PQsetnonblocking(pgsql, 1)) {
php_error(E_NOTICE,"PostgreSQL: Cannot set connection to nonblocking mode in pg_get_result()");
}
pgsql_result = PQgetResult(pgsql);
if (!pgsql_result) {
/* no result */
RETURN_FALSE;
}
if (PQsetnonblocking(pgsql, 0)) {
php_error(E_NOTICE,"PostgreSQL: Cannot set connection to blocking mode in pg_get_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);
}
/* }}} */
#endif #endif
/* /*

View file

@ -94,6 +94,12 @@ PHP_FUNCTION(pg_end_copy);
PHP_FUNCTION(pg_client_encoding); PHP_FUNCTION(pg_client_encoding);
PHP_FUNCTION(pg_set_client_encoding); PHP_FUNCTION(pg_set_client_encoding);
#endif #endif
PHP_FUNCTION(pg_reset);
PHP_FUNCTION(pg_status);
PHP_FUNCTION(pg_send_query);
PHP_FUNCTION(pg_request_cancel);
PHP_FUNCTION(pg_get_result);
PHP_FUNCTION(pg_is_busy);
void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS,int persistent); void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS,int persistent);
int php_pgsql_get_default_link(INTERNAL_FUNCTION_PARAMETERS); int php_pgsql_get_default_link(INTERNAL_FUNCTION_PARAMETERS);
@ -102,7 +108,7 @@ void php_pgsql_get_result_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type);
char *get_field_name(PGconn *pgsql, Oid oid, HashTable *list); char *get_field_name(PGconn *pgsql, Oid oid, HashTable *list);
void php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type); void php_pgsql_get_field_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type);
void php_pgsql_data_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type); void php_pgsql_data_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type);
void php_pgsql_do_async(INTERNAL_FUNCTION_PARAMETERS,int entry_type);
typedef struct pgLofp { typedef struct pgLofp {
PGconn *conn; PGconn *conn;