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
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 = {
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);
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);
dbcancel(H->link);
pdo_dblib_err_dtor(&H->err);
-
+
return 1;
}
pdo_dblib_db_handle *H = S->H;
struct pdo_column_data *col;
char *fname;
-
+
if(colno >= stmt->column_count || colno < 0) {
return FAILURE;
}
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 */
pdo_dblib_stmt_next_rowset, /* nextrow */
pdo_dblib_stmt_cursor_closer
};
-
{
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;
DBPROCESS *link;
pdo_dblib_err err;
+ unsigned stringify_uniqueidentifier:1;
} pdo_dblib_db_handle;
typedef struct {
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
--- /dev/null
+--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"