Hi Internals, hi Timm, On Sat, 2004-01-24 at 03:17, Timm Friebe wrote: > @- Fixed bug #22403 "PHP crashes when executing a sql procedure without > @ parameters" (Timm) > @- Fixed memory leak in sybase_set_message_handler() (Timm) > # Fixed bug with large numerics correctly (initial fix in r. 1.76 failed > # for MAX_LONG + 1, for example) > > > http://cvs.php.net/diff.php/php-src/ext/sybase_ct/php_sybase_ct.c?r1=1.88&r2=1.89&ty=u
[...] > static int php_sybase_fetch_result_row (sybase_result *result, int numrows) > @@ -1057,7 +1066,14 @@ > case 1: > convert_to_long(&result->data[i][j]); > break; > -case 2: > +case 2: > + /* We also get numbers that are actually integers here due to the check on > + * precision against > 9 (ranges are -1E10 to -1E9 and 1E9 to 1E10). As we > + * cannot be sure that they "fit" into MIN_LONG <= x <= MAX_LONG, we call > + * convert_to_double() on them. This is a small performance penalty, but > + * ensures that "select 2147483648" will be a float and "select 2147483647" > + * will be become an int. > + */ > convert_to_double(&result->data[i][j]); > break; > > } (reindented quote to better fit into email) [...] > @@ -1167,7 +1184,7 @@ > case CS_DECIMAL_TYPE: > result->datafmt[i].maxlength = > result->datafmt[i].precision + 3; > /* numeric(10) vs numeric(10, 1) */ > - result->numerics[i] = (result->datafmt[i].scale == 0 > && result->datafmt[i].precision <= 10) ? 1 : 2; > + result->numerics[i] = (result->datafmt[i].scale == 0 > && result->datafmt[i].precision <= 9) ? 1 : 2; > break; > default: > result->datafmt[i].maxlength++; This patch (committed with rev. 1.89 in ext/sybase_ct/php_sybase_ct.c) introduces a behaviour I consider broken: # select 2147483647 becomes an int because Sybase automatically converts the input into an int (ints have precision 0 (or NULL). # select 2147483648 becomes a float because Sybase convert this into a numeric(10,0), that is a numeric with precision 10. This numeric then will be converted into a float (because of the code in the second quote). This seems to be good, but this only works because the input is being autoconverted by Sybase into a suitable datatype. Autoconversion does, however, not apply to table columns (as they already have a type). Thus, the introduced decision (int or float depending on precision of type) applies to all rows of a result. Image a column of type numeric(10,0)¹. Insert a row with value 1. Select it, and it will be converted into float(1) - the columns precision is still 10. One may now say, this is good, because you want one column be mapped to just one datatype in the client application. I think, because of PHP's loose typing, it'd be better to get an int as long as possible and only get floats when values exceed MAX_INT. This would also meet the description from above's comment. Attached is a patch which adds this; it is also available at: http://document-root.de/patch/float-vs-int-php_sybase_ct.c.diff Feedback appreciated. Regards, -Alex 1] Of course, we're only talking about numerics with scale 0.
Index: ext/sybase_ct/php_sybase_ct.c =================================================================== RCS file: /repository/php-src/ext/sybase_ct/php_sybase_ct.c,v retrieving revision 1.93 diff -u -r1.93 php_sybase_ct.c --- ext/sybase_ct/php_sybase_ct.c 16 Apr 2004 16:27:13 -0000 1.93 +++ ext/sybase_ct/php_sybase_ct.c 14 May 2004 15:27:12 -0000 @@ -1135,6 +1135,13 @@ * will be become an int. */ convert_to_double(&result->data[i][j]); + + /* If the result is smaller than LONG_MAX, it would still fit into + * an int, so convert it. + */ + if (result->data[i][j].value.dval <= (double)LONG_MAX) { + convert_to_long(&result->data[i][j]); + } break; } }
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php