Re: cvs: php-src /ext/sybase_ct php_sybase_ct.c

From: Date: Fri, 14 May 2004 15:34:04 +0000
Subject: Re: cvs: php-src /ext/sybase_ct php_sybase_ct.c
References: 1  Groups: php.internals 
Request: Send a blank email to internals+get-9855@lists.php.net to get a copy of this message
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.

Attachment: [text/x-patch] float-vs-int-php_sybase_ct.c.diff
« previous php.internals (#9855) next »