thekid Mon Jul 12 17:07:21 2004 EDT Modified files: (Branch: PHP_4_3) /php-src/ext/sybase_ct php_sybase_ct.c Log: - Fixed bug #29064 (Exact numeric/decimal/money datatypes lose precision) - Fixed bug #27843 (sybase_query() triggers (spurious?) notices when query is a stored procedure) - Fixed multiple memory leaks with sybase_unbuffered_query() - Changed sybase_query() to ignore store_results = false in buffering mode, it would yield unpredictable results - Fixed sybase_unbuffered_query() when used with store_results = false - Changed sybase_fetch_object() to ignore second argument when passed as NULL - Made sybase_data_seek() error message more verbose - Fixed memory leak in shutdown when not all rows where selected in an unbuffered query CVS ---------------------------------------------------------------------- http://cvs.php.net/diff.php/php-src/ext/sybase_ct/php_sybase_ct.c?r1=1.73.2.16&r2=1.73.2.17&ty=u Index: php-src/ext/sybase_ct/php_sybase_ct.c diff -u php-src/ext/sybase_ct/php_sybase_ct.c:1.73.2.16 php-src/ext/sybase_ct/php_sybase_ct.c:1.73.2.17 --- php-src/ext/sybase_ct/php_sybase_ct.c:1.73.2.16 Fri May 21 17:00:19 2004 +++ php-src/ext/sybase_ct/php_sybase_ct.c Mon Jul 12 17:07:21 2004 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_sybase_ct.c,v 1.73.2.16 2004/05/21 21:00:19 edink Exp $ */ +/* $Id: php_sybase_ct.c,v 1.73.2.17 2004/07/12 21:07:21 thekid Exp $ */ #ifdef HAVE_CONFIG_H @@ -118,13 +118,12 @@ return 0; } - static void _free_sybase_result(sybase_result *result) { int i, j; if (result->data) { - for (i=0; i<(result->store ? result->num_rows : 0); i++) { + for (i = 0; i < (result->store ? result->num_rows : MIN(1, result->num_rows)); i++) { for (j=0; j<result->num_fields; j++) { zval_dtor(&result->data[i][j]); } @@ -144,10 +143,21 @@ efree(result); } +/* Forward declaration */ +static int php_sybase_finish_results (sybase_result *result); + static void php_free_sybase_result(zend_rsrc_list_entry *rsrc TSRMLS_DC) { sybase_result *result = (sybase_result *)rsrc->ptr; + /* Check to see if we've read all rows */ + if (result->sybase_ptr && result->sybase_ptr->active_result_index) { + if (result->sybase_ptr->cmd) { + ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_ALL); + } + php_sybase_finish_results(result); + } + _free_sybase_result(result); } @@ -1040,11 +1050,15 @@ case CS_PARAM_RESULT: case CS_ROW_RESULT: /* Unexpected results, cancel them. */ - case CS_STATUS_RESULT: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Sybase: Unexpected results, cancelling current"); ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_CURRENT); break; + case CS_STATUS_RESULT: + /* Status result from a stored procedure, cancel it but do not tell user */ + ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_CURRENT); + break; + default: php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Sybase: Unexpected results, cancelling all"); ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_ALL); @@ -1085,6 +1099,19 @@ return retcode; } +#define RETURN_DOUBLE_VAL(result, buf, length) \ + if ((length - 1) <= EG(precision)) { \ + errno = 0; \ + Z_DVAL(result) = strtod(buf, NULL); \ + if (errno != ERANGE) { \ + Z_TYPE(result) = IS_DOUBLE; \ + } else { \ + ZVAL_STRINGL(&result, buf, length- 1, 1); \ + } \ + } else { \ + ZVAL_STRINGL(&result, buf, length- 1, 1); \ + } + static int php_sybase_fetch_result_row (sybase_result *result, int numrows) { int i, j; @@ -1105,7 +1132,6 @@ } */ - /* i= result->num_rows++; */ result->num_rows++; i= result->store ? result->num_rows- 1 : 0; if (i >= result->blocks_initialized*SYBASE_ROWS_BLOCK) { @@ -1115,27 +1141,48 @@ result->data[i] = (zval *) safe_emalloc(sizeof(zval), result->num_fields, 0); } - for (j=0; j<result->num_fields; j++) { + 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])); + } + if (result->indicators[j] == -1) { /* null value */ ZVAL_NULL(&result->data[i][j]); } else { - Z_STRLEN(result->data[i][j]) = result->lengths[j]-1; /* we don't need the NULL in the length */ - Z_STRVAL(result->data[i][j]) = estrndup(result->tmp_buffer[j], result->lengths[j]); - Z_TYPE(result->data[i][j]) = IS_STRING; - switch (result->numerics[j]) { - case 1: - convert_to_long(&result->data[i][j]); + case 1: { + /* This indicates a long */ + ZVAL_LONG(&result->data[i][j], strtol(result->tmp_buffer[j], NULL, 10)); break; - case 2: - convert_to_double(&result->data[i][j]); + } + + case 2: { + /* This indicates a float */ + RETURN_DOUBLE_VAL(result->data[i][j], result->tmp_buffer[j], result->lengths[j]); break; - case 3: - /* This signals we have an integer datatype, but we need to convert to double if we - * overflow. - */ - convert_scalar_to_number(&result->data[i][j] TSRMLS_CC); + } + + case 3: { + /* This indicates either a long or a float, which ever fits */ + errno = 0; + Z_LVAL(result->data[i][j]) = strtol(result->tmp_buffer[j], NULL, 10); + if (errno == ERANGE) { + + /* An overflow occurred, so try to fit it into a double */ + RETURN_DOUBLE_VAL(result->data[i][j], result->tmp_buffer[j], result->lengths[j]); + break; + } + Z_TYPE(result->data[i][j]) = IS_LONG; break; + } + + default: { + /* This indicates anything else, return it as string */ + ZVAL_STRINGL(&result->data[i][j], result->tmp_buffer[j], result->lengths[j]- 1, 1); + break; + } } } } @@ -1278,9 +1325,12 @@ Z_TYPE(result->fields[i]) = result->types[i]; } - retcode= php_sybase_fetch_result_row(result, buffered ? 1 : -1); - if (retcode == CS_FAIL) { - return NULL; + if (buffered) { + retcode = CS_SUCCEED; + } else { + if ((retcode = php_sybase_fetch_result_row(result, -1)) == CS_FAIL) { + return NULL; + } } result->last_retcode = retcode; @@ -1320,9 +1370,14 @@ if (zend_get_parameters_ex(3, &query, &sybase_link_index, &store_mode)==FAILURE) { RETURN_FALSE; } + if (!buffered) { + php_error_docref(NULL TSRMLS_CC, E_NOTICE, "cannot use non-storing mode with buffered queries"); + store = 1; + } else { + convert_to_long_ex(store_mode); + store= (Z_LVAL_PP(store_mode) != 0); + } id = -1; - convert_to_long_ex(store_mode); - store= (Z_LVAL_PP(store_mode) != 0); break; default: WRONG_PARAM_COUNT; @@ -1760,19 +1815,20 @@ switch (Z_TYPE_PP(object)) { case IS_OBJECT: - ce= Z_OBJCE_PP(object); + ce = Z_OBJCE_PP(object); break; - default: + case IS_NULL: + break; + default: { convert_to_string_ex(object); zend_str_tolower(Z_STRVAL_PP(object), Z_STRLEN_PP(object)); - zend_hash_find(EG(class_table), Z_STRVAL_PP(object), Z_STRLEN_PP(object)+1, (void **)&ce); - - if (!ce) { + if (zend_hash_find(EG(class_table), Z_STRVAL_PP(object), Z_STRLEN_PP(object)+1, (void **)&ce) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Sybase: Class %s has not been declared", Z_STRVAL_PP(object)); - ce= ZEND_STANDARD_CLASS_DEF_PTR; } + } } - + + /* Reset no. of arguments to 1 so that we can use INTERNAL_FUNCTION_PARAM_PASSTHRU */ ht= 1; } @@ -1780,7 +1836,7 @@ if (Z_TYPE_P(return_value)==IS_ARRAY) { object_and_properties_init( return_value, - object ? ce : ZEND_STANDARD_CLASS_DEF_PTR, + ce ? ce : ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value) ); } @@ -1821,11 +1877,11 @@ /* Unbuffered ? */ if (result->last_retcode != CS_END_DATA && result->last_retcode != CS_END_RESULTS && Z_LVAL_PP(offset)>=result->num_rows) { - php_sybase_fetch_result_row(result, Z_LVAL_PP(offset)); + php_sybase_fetch_result_row(result, Z_LVAL_PP(offset)+ 1); } if (Z_LVAL_PP(offset)<0 || Z_LVAL_PP(offset)>=result->num_rows) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Bad row offset"); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Bad row offset %ld, must be betweem 0 and %d", Z_LVAL_PP(offset), result->num_rows - 1); RETURN_FALSE; }
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php