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

Reply via email to