mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Added async query functions
This commit is contained in:
parent
b11d1eb440
commit
db8bb9f23c
2 changed files with 294 additions and 3 deletions
|
@ -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,6 +756,7 @@ 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;
|
||||||
|
@ -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)
|
||||||
|
@ -1963,6 +2015,239 @@ 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
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue