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

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
This commit is contained in:
Alexander Zhuravlev 2016-07-04 12:47:18 +03:00 committed by Anatol Belski
parent 433976f931
commit a000bff2c3
5 changed files with 112 additions and 16 deletions

View 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);

View 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
};

View 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;

View 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

View File

@ -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"