Re: cvs: php-src /ext/sybase_ct php_sybase_ct.c
| From: | Alex Kiesel | 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
Attachment: [text/x-patch] float-vs-int-php_sybase_ct.c.diff