Handle SQLDECIMAL/SQLNUMERIC types, which are used by later TDS versions
authorAdam Baratz <adambaratz@php.net>
Tue, 13 Sep 2016 20:26:38 +0000 (16:26 -0400)
committerAdam Baratz <adambaratz@php.net>
Tue, 13 Sep 2016 20:32:37 +0000 (16:32 -0400)
ext/pdo_dblib/README
ext/pdo_dblib/dblib_stmt.c
ext/pdo_dblib/tests/config.inc
ext/pdo_dblib/tests/types.phpt

index 15f8d147a01ee0f6b63893530d068d0cd2ee614d..e833c74b6a2e99af60f3eae1f4a08ee2be825191 100644 (file)
@@ -9,4 +9,15 @@ The following database products are free for testing:
        - Microsoft SQL Server Express (Windows Only)
        - Sybase Adaptive Server (Windows, Linux, *NIX)
        - Microsoft SQL Server Azure (One Month Trial Cloud Service)
-       
+
+You must set the following environment variables to run the tests:
+       - PDO_DBLIB_TEST_DSN  - DSN (e.g., dblib:host=localhost;dbname=test)
+       - PDO_DBLIB_TEST_USER - database user
+       - PDO_DBLIB_TEST_PASS - database user password
+
+This extension supports multiple versions of the TDS protocol. There are
+behavioral differences between versions. When making changes, it's recommended
+to test across all supported versions. You can specify a version using a version
+parameter in the DSN. See dblib_driver.c:pdo_dblib_handle_factory() for valid
+values. Some tests check version-specific behavior by parsing this string, so
+it's best to use the DSN (rather than freetds.conf, etc.) to set the version.
index 8ec4f782fd85149a749293b34e316531e20adf69..311d856d55074de988dffc0d2a04b95de42e4089 100644 (file)
@@ -266,6 +266,11 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
        if (data_len != 0 || data != NULL) {
                if (stmt->dbh->stringify) {
                        switch (coltype) {
+                               case SQLDECIMAL:
+                               case SQLNUMERIC:
+                               case SQLMONEY:
+                               case SQLMONEY4:
+                               case SQLMONEYN:
                                case SQLFLT4:
                                case SQLFLT8:
                                case SQLINT4:
@@ -361,18 +366,16 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
 
                                        break;
                                }
+                               case SQLDECIMAL:
+                               case SQLNUMERIC:
                                case SQLMONEY:
                                case SQLMONEY4:
                                case SQLMONEYN: {
-                                       DBFLT8 money_value;
-                                       dbconvert(NULL, coltype, data, 8, SQLFLT8, (LPBYTE)&money_value, -1);
+                                       DBFLT8 float_value;
+                                       dbconvert(NULL, coltype, data, 8, SQLFLT8, (LPBYTE)&float_value, -1);
 
                                        zv = emalloc(sizeof(zval));
-                                       ZVAL_DOUBLE(zv, money_value);
-
-                                       if (stmt->dbh->stringify) {
-                                               convert_to_string(zv);
-                                       }
+                                       ZVAL_DOUBLE(zv, float_value);
 
                                        break;
                                }
index 5b7b4d43273fb52a855d8c9bc94ff3aebd8523c5..346de0f8ca730e7b217a070ebe3cb696d719d45a 100644 (file)
@@ -1,5 +1,21 @@
 <?php
 
+function get_tds_version() {
+       global $dsn;
+
+       $dsn_parts = explode(':', $dsn, 2);
+       if ($dsn_parts[0] == 'dblib') { // uri is an option, which we'll ignore
+               foreach (explode(';', $dsn_parts[1]) as $arg) {
+                       $arg = explode('=', $arg);
+                       if ($arg[0] == 'version') {
+                               return $arg[1];
+                       }
+               }
+       }
+
+       return null;
+}
+
 if (false !== getenv('PDO_DBLIB_TEST_DSN')) 
        $dsn = getenv('PDO_DBLIB_TEST_DSN');
 else
index dd849adcf81905d01f22a746098fb96d54d37998..04b8568f4861bb091086e3f1d750a91aff4c3ed6 100644 (file)
@@ -9,14 +9,28 @@ require __DIR__ . '/config.inc';
 <?php
 require __DIR__ . '/config.inc';
 
+function get_expected_float_string() {
+       switch (get_tds_version()) {
+               case '5.0':
+               case '6.0':
+               case '7.0':
+               case '7.1':
+               case '7.2':
+               case '8.0':
+                       return '10.500';
+               default:
+                       return '10.5';
+       }
+}
+
 $sql = "
        SELECT
                'foo' AS [char],
                CAST('2030-01-01 23:59:59' AS DATETIME) AS [datetime],
                CAST(0 AS BIT) AS [false],
-               10.5 AS [float],
+               10.500 AS [float],
                1000 AS [int],
-               CAST(10.5 AS MONEY) AS [money],
+               CAST(10.500 AS MONEY) AS [money],
                CAST('1950-01-18 23:00:00' AS SMALLDATETIME) as [smalldatetime],
                CAST(1 AS BIT) AS [true]
 ";
@@ -40,9 +54,9 @@ $row = $stmt->fetch(PDO::FETCH_ASSOC);
 var_dump($row['char'] === 'foo');
 var_dump($row['datetime'] === '2030-01-01 23:59:59');
 var_dump($row['false'] === '0');
-var_dump($row['float'] === '10.5');
+var_dump($row['float'] === get_expected_float_string());
 var_dump($row['int'] === '1000');
-var_dump($row['money'] === '10.5');
+var_dump($row['money'] === '10.50');
 var_dump($row['smalldatetime'] === '1950-01-18 23:00:00');
 var_dump($row['true'] === '1');