]> granicus.if.org Git - php/commitdiff
pdo_dblib: stringify uniqidentifier field
authorAlexander Zhuravlev <a.zhuravlev@ekomobile.ru>
Mon, 4 Jul 2016 09:47:18 +0000 (12:47 +0300)
committerAnatol Belski <ab@php.net>
Thu, 25 Aug 2016 17:37:21 +0000 (19:37 +0200)
Keep old 5.6 behavior: return Uniqidentifier value as 36-byte hex string (not binary),
when PDO::ATTR_STRINGIFY_FETCHES is TRUE

pdo_dblib: Stringify uniqidentifier field

Keep old 5.6 behavior: return Uniqidentifier value as 36-byte hex string (not binary),
when PDO::ATTR_STRINGIFY_FETCHES is TRUE

Tests added.

pdo_dblib: Stringify uniqidentifier field

Keep old 5.6 behavior: return Uniqidentifier value as 36-byte hex string (not binary),
when PDO::ATTR_STRINGIFY_FETCHES is TRUE

Tests fix.

pdo_dblib: Stringify uniqueidentifier field Added separate PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER attribute instead of PDO::ATTR_STRINGIFY_FETCHES.

pdo_dblib: Stringify uniqueidentifier field Added `getAttribute` support for PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER.

Simplify storage of stringify_uniqueidentifier attribute

ext/pdo_dblib/dblib_driver.c
ext/pdo_dblib/dblib_stmt.c
ext/pdo_dblib/pdo_dblib.c
ext/pdo_dblib/php_pdo_dblib_int.h
ext/pdo_dblib/tests/stringify_uniqueidentifier.phpt [new file with mode: 0644]

index d071027e59df0ee763e4330aa3f1fc9df763e8e4..0a55cc4ff74e0c49625d1fd7097e1d08ae946e0f 100644 (file)
@@ -280,16 +280,28 @@ static int dblib_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
        switch(attr) {
                case PDO_ATTR_TIMEOUT:
                        return 0;
+
+               case PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER:
+                       ((pdo_dblib_db_handle *)dbh->driver_data)->stringify_uniqueidentifier = zval_get_long(val);
+                       return 1;
+
                default:
                        return 1;
        }
-
 }
 
 static int dblib_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_value)
 {
-       /* dblib_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data; */
-       return 0;
+       switch (attr) {
+               case PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER:
+                       ZVAL_BOOL(return_value, ((pdo_dblib_db_handle *)dbh->driver_data)->stringify_uniqueidentifier);
+                       break;
+
+               default:
+                       return 0;
+       }
+
+       return 1;
 }
 
 static struct pdo_dbh_methods dblib_methods = {
@@ -347,6 +359,15 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
        
        php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, nvars);
 
+       H = pecalloc(1, sizeof(*H), dbh->is_persistent);
+       H->login = dblogin();
+       H->err.sqlstate = dbh->error_code;
+       H->stringify_uniqueidentifier = 0;
+
+       if (!H->login) {
+               goto cleanup;
+       }
+
        if (driver_options) {
                int connect_timeout = pdo_attr_lval(driver_options, PDO_DBLIB_ATTR_CONNECTION_TIMEOUT, -1);
                int query_timeout = pdo_attr_lval(driver_options, PDO_DBLIB_ATTR_QUERY_TIMEOUT, -1);
@@ -361,14 +382,8 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
 
                dbsetlogintime(connect_timeout); /* Connection/Login Timeout */
                dbsettime(query_timeout); /* Statement Timeout */
-       }
 
-       H = pecalloc(1, sizeof(*H), dbh->is_persistent);
-       H->login = dblogin();
-       H->err.sqlstate = dbh->error_code;
-
-       if (!H->login) {
-               goto cleanup;
+               H->stringify_uniqueidentifier = pdo_attr_lval(driver_options, PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER, 0);
        }
 
        DBERRHANDLE(H->login, (EHANDLEFUNC) pdo_dblib_error_handler);
index a1055434d37d7b956290c0b8663e88c2f72dc992..8ec4f782fd85149a749293b34e316531e20adf69 100644 (file)
@@ -120,7 +120,7 @@ static int pdo_dblib_stmt_cursor_closer(pdo_stmt_t *stmt)
        dbcancel(H->link);
 
        pdo_dblib_err_dtor(&H->err);
-       
+
        return 1;
 }
 
@@ -213,7 +213,7 @@ static int pdo_dblib_stmt_describe(pdo_stmt_t *stmt, int colno)
        pdo_dblib_db_handle *H = S->H;
        struct pdo_column_data *col;
        char *fname;
-       
+
        if(colno >= stmt->column_count || colno < 0)  {
                return FAILURE;
        }
@@ -376,16 +376,28 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
 
                                        break;
                                }
+
 #ifdef SQLUNIQUE
                                case SQLUNIQUE: {
 #else
                                case 36: { /* FreeTDS hack */
 #endif
-                                       zv = emalloc(sizeof(zval));
-                                       ZVAL_STRINGL(zv, data, 16); /* uniqueidentifier is a 16-byte binary number */
+                                       if (H->stringify_uniqueidentifier) { // 36-char hex string representation
+                                               tmp_data_len = 36;
+                                               tmp_data = safe_emalloc(tmp_data_len, sizeof(char), 1);
+                                               data_len = (unsigned int) dbconvert(NULL, SQLUNIQUE, (BYTE*)data, data_len, SQLCHAR, (BYTE*)tmp_data, tmp_data_len);
+                                               php_strtoupper(tmp_data, data_len);
+                                               zv = emalloc(sizeof(zval));
+                                               ZVAL_STRINGL(zv, tmp_data, data_len);
+                                               efree(tmp_data);
 
+                                       } else { // a 16-byte binary representation
+                                               zv = emalloc(sizeof(zval));
+                                               ZVAL_STRINGL(zv, data, 16);
+                                       }
                                        break;
                                }
+
                                default: {
                                        if (dbwillconvert(coltype, SQLCHAR)) {
                                                tmp_data_len = 32 + (2 * (data_len)); /* FIXME: We allocate more than we need here */
@@ -479,4 +491,3 @@ struct pdo_stmt_methods dblib_stmt_methods = {
        pdo_dblib_stmt_next_rowset, /* nextrow */
        pdo_dblib_stmt_cursor_closer
 };
-
index 578be2ee10b1eb8bccac2ec8ee867b3de86cc88e..b855224c683c86832f76ffa4d37631f697178185 100644 (file)
@@ -179,6 +179,7 @@ PHP_MINIT_FUNCTION(pdo_dblib)
 {
        REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_CONNECTION_TIMEOUT", (long) PDO_DBLIB_ATTR_CONNECTION_TIMEOUT);
        REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_QUERY_TIMEOUT", (long) PDO_DBLIB_ATTR_QUERY_TIMEOUT);
+       REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER", (long) PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER);
 
        if (FAIL == dbinit()) {
                return FAILURE;
index 01586881d55f1e3df4ae57eeb15c10b0c6ba3707..87a0038ef4cfb516a1da664eb02bbaddc6c8aec6 100644 (file)
@@ -113,6 +113,7 @@ typedef struct {
        DBPROCESS       *link;
 
        pdo_dblib_err err;
+       unsigned stringify_uniqueidentifier:1;
 } pdo_dblib_db_handle;
 
 typedef struct {
@@ -142,7 +143,8 @@ ZEND_EXTERN_MODULE_GLOBALS(dblib)
 
 enum {
        PDO_DBLIB_ATTR_CONNECTION_TIMEOUT = PDO_ATTR_DRIVER_SPECIFIC,
-       PDO_DBLIB_ATTR_QUERY_TIMEOUT
+       PDO_DBLIB_ATTR_QUERY_TIMEOUT,
+       PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER,
 };
 
 #endif
diff --git a/ext/pdo_dblib/tests/stringify_uniqueidentifier.phpt b/ext/pdo_dblib/tests/stringify_uniqueidentifier.phpt
new file mode 100644 (file)
index 0000000..79847bf
--- /dev/null
@@ -0,0 +1,67 @@
+--TEST--
+PDO_DBLIB: Uniqueidentifier column data type stringifying
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_dblib')) die('skip not loaded');
+require __DIR__ . '/config.inc';
+?>
+--FILE--
+<?php
+require __DIR__ . '/config.inc';
+
+
+$testGUID = '82A88958-672B-4C22-842F-216E2B88E72A';
+$testGUIDBinary = base64_decode('WImogitnIkyELyFuK4jnKg==');
+
+$sql = "SELECT CAST('$testGUID' as uniqueidentifier) as [guid]";
+
+//--------------------------------------------------------------------------------
+// 1. Get and Set the attribute
+//--------------------------------------------------------------------------------
+$db->setAttribute(PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER, true);
+var_dump(true === $db->getAttribute(PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER));
+$db->setAttribute(PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER, false);
+var_dump(false === $db->getAttribute(PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER));
+
+
+//--------------------------------------------------------------------------------
+// 2. Binary
+//--------------------------------------------------------------------------------
+$stmt = $db->query($sql);
+$row = $stmt->fetch(PDO::FETCH_ASSOC);
+
+var_dump($row['guid'] === $testGUIDBinary);
+
+
+//--------------------------------------------------------------------------------
+// 3. PDO::ATTR_STRINGIFY_FETCHES must not affect `uniqueidentifier` representation
+//--------------------------------------------------------------------------------
+$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);
+$stmt = $db->query($sql);
+$row = $stmt->fetch(PDO::FETCH_ASSOC);
+$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
+
+var_dump($row['guid'] === $testGUIDBinary);
+
+
+//--------------------------------------------------------------------------------
+// 4. Stringifying
+// ! With TDS protocol version <7.0 binary will be returned and the test will fail !
+// TODO: something from PDO::ATTR_SERVER_VERSION, PDO::ATTR_CLIENT_VERSION or PDO::ATTR_SERVER_INFO should be used
+// to get TDS version and skip this test in this case.
+//--------------------------------------------------------------------------------
+$db->setAttribute(PDO::DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER, true);
+$stmt = $db->query($sql);
+$row = $stmt->fetch(PDO::FETCH_ASSOC);
+
+var_dump($row['guid'] === $testGUID);
+var_dump($row['guid']);
+
+?>
+--EXPECT--
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+string(36) "82A88958-672B-4C22-842F-216E2B88E72A"