ID: 48675
Comment by: murali_dharan_2000 at yahoo dot com
Reported By: lo at readyon dot com
Status: Open
Bug Type: Sybase-ct (ctlib) related
Operating System: Mac OS X 10.5.7 (9J61)
PHP Version: 5.2.10
New Comment:
The proposed solution did not work for me on PHP 5.3.0 on Linux x86-64.
This functionality is really useful to have in PHP as the power of
stored procedures in Sybase is the ability to return multiple result
sets and PHP needs to be enhanced to handle the same.
Previous Comments:
------------------------------------------------------------------------
[2009-06-24 13:40:16] lo at readyon dot com
Here is a patch to add support for sybase_next_result() for 5.2.9:
diff -rupN ../orig/php-5.2.9/ext/sybase_ct/php_sybase_ct.c
ext/sybase_ct/php_sybase_ct.c
--- ../orig/php-5.2.9/ext/sybase_ct/php_sybase_ct.c 2008-12-31
05:17:46.000000000 -0600
+++ ext/sybase_ct/php_sybase_ct.c 2009-06-24 08:28:52.000000000
-0500
@@ -47,8 +47,9 @@ zend_function_entry sybase_functions[] =
PHP_FE(sybase_close, NULL)
PHP_FE(sybase_select_db, NULL)
PHP_FE(sybase_query, NULL)
- PHP_FE(sybase_unbuffered_query, NULL)
PHP_FE(sybase_free_result, NULL)
+ PHP_FE(sybase_unbuffered_query, NULL)
+ PHP_FE(sybase_next_result, NULL)
PHP_FE(sybase_get_last_message, NULL)
PHP_FE(sybase_num_rows, NULL)
PHP_FE(sybase_num_fields, NULL)
@@ -73,6 +74,7 @@ zend_function_entry sybase_functions[] =
PHP_FALIAS(mssql_select_db, sybase_select_db, NULL)
PHP_FALIAS(mssql_query, sybase_query, NULL)
PHP_FALIAS(mssql_unbuffered_query, sybase_unbuffered_query,
NULL)
+ PHP_FALIAS(mssql_next_result, sybase_next_result, NULL)
PHP_FALIAS(mssql_free_result, sybase_free_result, NULL)
PHP_FALIAS(mssql_get_last_message, sybase_get_last_message,
NULL)
PHP_FALIAS(mssql_num_rows, sybase_num_rows, NULL)
@@ -1052,7 +1054,8 @@ static int php_sybase_finish_results(syb
efree_n(result->numerics);
efree_n(result->types);
for (i=0; i<result->num_fields; i++) {
- efree(result->tmp_buffer[i]);
+ if (result->tmp_buffer != NULL)
+ efree(result->tmp_buffer[i]);
}
efree_n(result->tmp_buffer);
@@ -1085,7 +1088,14 @@ static int php_sybase_finish_results(syb
case CS_ROW_RESULT:
/* Unexpected results, cancel them. */
php_error_docref(NULL TSRMLS_CC,
E_NOTICE, "Sybase: Unexpected results, cancelling current");
- ct_cancel(NULL, result->sybase_ptr-
>cmd, CS_CANCEL_CURRENT);
+ // !!!:KLS:20090624 Do not cancel when there are
additional
+ // rows. THe command will be cancelled upon next
query if
+ // sybase_next_result() is not invoked.
+ // {
+ fail = 1;
+ retcode = CS_END_RESULTS;
+ // ct_cancel(NULL, result->sybase_ptr->cmd,
CS_CANCEL_CURRENT);
+ // }
break;
case CS_STATUS_RESULT:
@@ -1167,7 +1177,6 @@ static int php_sybase_fetch_result_row (
}
for (j = 0; j < result->num_fields; j++) {
-
/* If we are in non-storing mode, free the
previous result */
if (!result->store && result->num_rows > 1 &&
Z_TYPE(result->data[i][j]) == IS_STRING) {
efree(Z_STRVAL(result->data[i][j]));
@@ -1645,6 +1654,98 @@ PHP_FUNCTION(sybase_unbuffered_query)
{
php_sybase_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
}
+/* }}} */
+
+// MARK: sybase_next_result
+/* {{{ proto int sybase_next_result(int result)
+ Send Sybase query */
+PHP_FUNCTION(sybase_next_result)
+{
+ zval **db, **sybase_link_index;
+ int id;
+ char *cmdbuf;
+ sybase_link *sybase_ptr;
+ sybase_result *result;
+ int retcode;
+ int restype;
+
+ switch(ZEND_NUM_ARGS()) {
+ case 1:
+ if (zend_get_parameters_ex(1, &db) == FAILURE)
{
+ RETURN_FALSE;
+ }
+ id =
php_sybase_get_default_link(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ CHECK_LINK(id);
+ break;
+ case 2:
+ if (zend_get_parameters_ex(2, &db,
&sybase_link_index) == FAILURE) {
+ RETURN_FALSE;
+ }
+ id = -1;
+ break;
+ default:
+ WRONG_PARAM_COUNT;
+ break;
+ }
+
+ ZEND_FETCH_RESOURCE2(sybase_ptr, sybase_link *,
sybase_link_index, id, "Sybase-Link", le_link, le_plink);
+
+ /* Check to see if a previous sybase_unbuffered_query has read
all rows */
+ if (sybase_ptr->active_result_index) {
+ zval *tmp = NULL;
+
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "called
without first fetching all rows from a previous unbuffered query");
+ if (sybase_ptr->cmd) {
+ ct_cancel(NULL, sybase_ptr->cmd,
CS_CANCEL_ALL);
+ }
+
+ /* Get the resultset and free it */
+ ALLOC_ZVAL(tmp);
+ Z_LVAL_P(tmp)= sybase_ptr->active_result_index;
+ Z_TYPE_P(tmp)= IS_RESOURCE;
+ INIT_PZVAL(tmp);
+ ZEND_FETCH_RESOURCE(result, sybase_result *, &tmp, -1,
"Sybase result", le_result);
+
+ if (result) {
+ php_sybase_finish_results(result TSRMLS_CC);
+ }
+
+ zval_ptr_dtor(&tmp);
+ zend_list_delete(sybase_ptr->active_result_index);
+ sybase_ptr->active_result_index= 0;
+ }
+
+ retcode = ct_results(sybase_ptr->cmd, &restype);
+ //printf(" ct_results(): retcode=%d, restype=%d\n", retcode,
restype);
+ switch (retcode) {
+ case CS_SUCCEED:
+ result = php_sybase_fetch_result_set(sybase_ptr, 0, 1);
+ if (result == NULL) {
+ ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL);
+ sybase_ptr->dead = 1;
+ RETURN_FALSE;
+ }
+
+ /* Indicate we have data in case of buffered queries */
+ id= ZEND_REGISTER_RESOURCE(return_value, result,
le_result);
+ sybase_ptr->active_result_index= 0 ? id : 0;
+ break;
+
+ case CS_END_RESULTS:
+ /* No more result sets */
+ RETURN_FALSE;
+
+ case CS_FAIL:
+ ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL);
+ sybase_ptr->dead = 1;
+ /* Fall through */
+
+ case CS_CANCELED:
+ default:
+ RETURN_FALSE;
+ }
+}
+/* }}} */
/* {{{ proto bool sybase_free_result(int result)
Free result memory */
diff -rupN ../orig/php-5.2.9/ext/sybase_ct/php_sybase_ct.h
ext/sybase_ct/php_sybase_ct.h
--- ../orig/php-5.2.9/ext/sybase_ct/php_sybase_ct.h 2008-12-31
05:17:46.000000000 -0600
+++ ext/sybase_ct/php_sybase_ct.h 2009-06-23 11:44:01.000000000
-0500
@@ -42,6 +42,7 @@ PHP_FUNCTION(sybase_select_db);
PHP_FUNCTION(sybase_query);
PHP_FUNCTION(sybase_unbuffered_query);
PHP_FUNCTION(sybase_free_result);
+PHP_FUNCTION(sybase_next_result);
PHP_FUNCTION(sybase_get_last_message);
PHP_FUNCTION(sybase_num_rows);
PHP_FUNCTION(sybase_num_fields);
------------------------------------------------------------------------
[2009-06-24 13:38:09] lo at readyon dot com
Description:
------------
Sybase CTLib does not support fetching more than one result set from a
stored procedure. This seems to be a long standing issue detailed in
the
closed (status: bogus) issue #26636 and others, detailed in the user
comments on the page http://us3.php.net/manual/en/function.sybase-
query.php.
Reproduce code:
---------------
$conn = sybase_connect($server, $user, $pass);
sybase_select_db($db, $conn);
$result = sybase_query("sp_help $table", $conn);
do {
echo "Next result set...\n";
while ($row = sybase_fetch_assoc($result)) {
echo " - fetched row...\n";
}
} while ($result = sybase_next_result($conn)); // <- No such function
Expected result:
----------------
Many result sets, for example:
Next result set...
- fetched row
Next result set...
- fetched row
- fetched row
- fetched row
- fetched row
- fetched row
- fetched row
Next result set...
- fetched row
- fetched row
Next result set...
- fetched row
- fetched row
Next result set...
- fetched row
Next result set...
- fetched row
Next result set...
- fetched row
Next result set...
- fetched row
Next result set...
- fetched row
Next result set...
- fetched row
Actual result:
--------------
Next result set...
- fetched row
Then no supported function sybase_next_result().
------------------------------------------------------------------------
--
Edit this bug report at http://bugs.php.net/?id=48675&edit=1