|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2009-06-24 13:38 UTC] 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(). PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Thu Oct 30 17:00:01 2025 UTC |
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);I haven't looked at 5.3.0. However, the changes to php_sybase_ct.c are relatively straightforward: 1. Disable cancelling/closing after successful result php_sybase_finish_results() case CS_COMPUTE_RESULT: case CS_CURSOR_RESULT: case CS_PARAM_RESULT: case CS_ROW_RESULT: /* Unexpected results, cancel them. */ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Sybase: Unexpected results, cancelling 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; 2. Add a sybase_next_result() function and register these functions. /* {{{ proto int sybase_next_result(int conn) Fetch the next result set */ 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); 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; } } /* }}} */