On Fri, 2004-05-14 at 17:34, Alex Kiesel wrote: > Hi Internals, hi Timm, [...] > 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.
You're right, the decision needs to be made for each value while retrieving the rows. I've made a new patch and added a testcase, and, while doing so, corrected an older testcase (LONG_MIN is -2147483648, not -2147483647: [EMAIL PROTECTED]:~ > cat > long.c #include <machine/limits.h> int main(int argc, char* argv) { printf("%d - %d\n", LONG_MIN, LONG_MAX); } [EMAIL PROTECTED]:~ > make long cc -O -pipe long.c -o long [EMAIL PROTECTED]:~ > ./long -2147483648 - 2147483647 ) - Timm
Index: 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 --- php_sybase_ct.c 16 Apr 2004 16:27:13 -0000 1.93 +++ php_sybase_ct.c 15 May 2004 14:28:06 -0000 @@ -1127,14 +1127,16 @@ convert_to_long(&result->data[i][j]); break; 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; + case 3: + /* This signals we have an integer datatype, but we need to convert to double if we + * overflow. */ convert_to_double(&result->data[i][j]); + if (Z_DVAL(result->data[i][j]) >= LONG_MIN && Z_DVAL(result->data[i][j]) <= LONG_MAX) { + convert_to_long(&result->data[i][j]); + } break; } } @@ -1243,7 +1245,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 <= 9) ? 1 : 2; + result->numerics[i] = (result->datafmt[i].scale == 0) ? 3 : 2; break; default: result->datafmt[i].maxlength++; Index: tests/test_long.phpt =================================================================== RCS file: tests/test_long.phpt diff -N tests/test_long.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ tests/test_long.phpt 15 May 2004 14:28:06 -0000 @@ -0,0 +1,77 @@ +--TEST-- +Sybase-CT select LONG_MAX / LONG_MIN +--SKIPIF-- +<?php require('skipif.inc'); ?> +--FILE-- +<?php +/* This file is part of PHP test framework for ext/sybase_ct + * + * $Id: test_types.phpt,v 1.2 2004/01/24 15:18:52 thekid Exp $ + */ + + require('test.inc'); + + $db= sybase_connect_ex(); + var_dump(sybase_select_db('tempdb', $db)); + + // Create table and insert some values + var_dump(sybase_query('create table test_long (value numeric(10,0))')); + var_dump(sybase_query('insert test_long values (2147483646)')); // LONG_MAX - 1 + var_dump(sybase_query('insert test_long values (2147483647)')); // LONG_MAX + var_dump(sybase_query('insert test_long values (2147483648)')); // LONG_MAX + 1 + var_dump(sybase_query('insert test_long values (-2147483647)')); // LONG_MIN + 1 + var_dump(sybase_query('insert test_long values (-2147483648)')); // LONG_MIN + var_dump(sybase_query('insert test_long values (-2147483649)')); // LONG_MIN - 1 + + // Select values + var_dump(sybase_select_ex($db, 'select value from test_long')); + + // Drop table + var_dump(sybase_query('drop table test_long')); + + sybase_close($db); +?> +--EXPECTF-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +>>> Query: select value from test_long +<<< Return: resource +array(6) { + [0]=> + array(1) { + ["value"]=> + int(2147483646) + } + [1]=> + array(1) { + ["value"]=> + int(2147483647) + } + [2]=> + array(1) { + ["value"]=> + float(2147483648) + } + [3]=> + array(1) { + ["value"]=> + int(-2147483647) + } + [4]=> + array(1) { + ["value"]=> + int(-2147483648) + } + [5]=> + array(1) { + ["value"]=> + float(-2147483649) + } +} +bool(true) Index: tests/test_types.phpt =================================================================== RCS file: /repository/php-src/ext/sybase_ct/tests/test_types.phpt,v retrieving revision 1.2 diff -u -r1.2 test_types.phpt --- tests/test_types.phpt 24 Jan 2004 15:18:52 -0000 1.2 +++ tests/test_types.phpt 15 May 2004 14:28:06 -0000 @@ -14,8 +14,8 @@ $db= sybase_connect_ex(); var_dump(sybase_select_ex($db, 'select 1 as "integer", - -2147483647 as "integer_min", - -2147483648 as "integer_min_exceed", + -2147483648 as "integer_min", + -2147483649 as "integer_min_exceed", 2147483647 as "integer_max", 2147483648 as "integer_max_exceed", 1.0 as "float", @@ -33,8 +33,8 @@ --EXPECTF-- >>> Query: select 1 as "integer", - -2147483647 as "integer_min", - -2147483648 as "integer_min_exceed", + -2147483648 as "integer_min", + -2147483649 as "integer_min_exceed", 2147483647 as "integer_max", 2147483648 as "integer_max_exceed", 1.0 as "float", @@ -53,9 +53,9 @@ ["integer"]=> int(1) ["integer_min"]=> - int(-2147483647) + int(-2147483648) ["integer_min_exceed"]=> - float(-2147483648) + float(-2147483649) ["integer_max"]=> int(2147483647) ["integer_max_exceed"]=>
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php