mirror of
https://github.com/php/php-src.git
synced 2024-09-22 02:17:32 +00:00
Merge branch 'PHP-7.0'
* PHP-7.0: return zvals instead of strings, cast or not based on stringify attribute
This commit is contained in:
commit
2267812cd2
@ -232,7 +232,7 @@ static int pdo_dblib_stmt_describe(pdo_stmt_t *stmt, int colno)
|
||||
}
|
||||
|
||||
col->maxlen = dbcollen(H->link, colno+1);
|
||||
col->param_type = PDO_PARAM_STR;
|
||||
col->param_type = PDO_PARAM_ZVAL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -245,78 +245,161 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
|
||||
pdo_dblib_db_handle *H = S->H;
|
||||
|
||||
int coltype;
|
||||
unsigned int tmp_len;
|
||||
char *tmp_ptr = NULL;
|
||||
char *data, *tmp_data;
|
||||
unsigned int data_len, tmp_data_len;
|
||||
zval *zv = NULL;
|
||||
|
||||
coltype = dbcoltype(H->link, colno+1);
|
||||
data = dbdata(H->link, colno+1);
|
||||
data_len = dbdatlen(H->link, colno+1);
|
||||
|
||||
*len = dbdatlen(H->link, colno+1);
|
||||
*ptr = dbdata(H->link, colno+1);
|
||||
if (data_len != 0 || data != NULL) {
|
||||
if (stmt->dbh->stringify) {
|
||||
switch (coltype) {
|
||||
case SQLFLT4:
|
||||
case SQLFLT8:
|
||||
case SQLINT4:
|
||||
case SQLINT2:
|
||||
case SQLINT1:
|
||||
case SQLBIT: {
|
||||
if (dbwillconvert(coltype, SQLCHAR)) {
|
||||
tmp_data_len = 32 + (2 * (data_len)); /* FIXME: We allocate more than we need here */
|
||||
tmp_data = emalloc(tmp_data_len);
|
||||
data_len = dbconvert(NULL, coltype, data, data_len, SQLCHAR, tmp_data, -1);
|
||||
|
||||
if (*len == 0 && *ptr == NULL) {
|
||||
return 1;
|
||||
zv = emalloc(sizeof(zval));
|
||||
ZVAL_STRING(zv, tmp_data);
|
||||
|
||||
efree(tmp_data);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!zv) {
|
||||
switch (coltype) {
|
||||
case SQLCHAR:
|
||||
case SQLVARCHAR:
|
||||
case SQLTEXT: {
|
||||
#if ilia_0
|
||||
while (data_len>0 && data[data_len-1] == ' ') { /* nuke trailing whitespace */
|
||||
data_len--;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
case SQLVARBINARY:
|
||||
case SQLBINARY:
|
||||
case SQLIMAGE: {
|
||||
zv = emalloc(sizeof(zval));
|
||||
ZVAL_STRINGL(zv, data, data_len);
|
||||
|
||||
break;
|
||||
}
|
||||
case SQLDATETIME:
|
||||
case SQLDATETIM4: {
|
||||
int dl;
|
||||
DBDATEREC di;
|
||||
DBDATEREC dt;
|
||||
|
||||
dbconvert(H->link, coltype, data, -1, SQLDATETIME, (LPBYTE) &dt, -1);
|
||||
dbdatecrack(H->link, &di, (DBDATETIME *) &dt);
|
||||
|
||||
dl = spprintf(&tmp_data, 20, "%d-%02d-%02d %02d:%02d:%02d",
|
||||
#if defined(PHP_DBLIB_IS_MSSQL) || defined(MSDBLIB)
|
||||
di.year, di.month, di.day, di.hour, di.minute, di.second
|
||||
#else
|
||||
di.dateyear, di.datemonth+1, di.datedmonth, di.datehour, di.dateminute, di.datesecond
|
||||
#endif
|
||||
);
|
||||
|
||||
zv = emalloc(sizeof(zval));
|
||||
ZVAL_STRINGL(zv, tmp_data, dl);
|
||||
|
||||
efree(tmp_data);
|
||||
|
||||
break;
|
||||
}
|
||||
case SQLFLT4: {
|
||||
zv = emalloc(sizeof(zval));
|
||||
ZVAL_DOUBLE(zv, (double) (*(DBFLT4 *) data));
|
||||
|
||||
break;
|
||||
}
|
||||
case SQLFLT8: {
|
||||
zv = emalloc(sizeof(zval));
|
||||
ZVAL_DOUBLE(zv, (double) (*(DBFLT8 *) data));
|
||||
|
||||
break;
|
||||
}
|
||||
case SQLINT4: {
|
||||
zv = emalloc(sizeof(zval));
|
||||
ZVAL_LONG(zv, (long) ((int) *(DBINT *) data));
|
||||
|
||||
break;
|
||||
}
|
||||
case SQLINT2: {
|
||||
zv = emalloc(sizeof(zval));
|
||||
ZVAL_LONG(zv, (long) ((int) *(DBSMALLINT *) data));
|
||||
|
||||
break;
|
||||
}
|
||||
case SQLINT1:
|
||||
case SQLBIT: {
|
||||
zv = emalloc(sizeof(zval));
|
||||
ZVAL_LONG(zv, (long) ((int) *(DBTINYINT *) data));
|
||||
|
||||
break;
|
||||
}
|
||||
case SQLMONEY:
|
||||
case SQLMONEY4:
|
||||
case SQLMONEYN: {
|
||||
DBFLT8 money_value;
|
||||
dbconvert(NULL, coltype, data, 8, SQLFLT8, (LPBYTE)&money_value, -1);
|
||||
|
||||
zv = emalloc(sizeof(zval));
|
||||
ZVAL_DOUBLE(zv, money_value);
|
||||
|
||||
if (stmt->dbh->stringify) {
|
||||
convert_to_string(zv);
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (dbwillconvert(coltype, SQLCHAR)) {
|
||||
tmp_data_len = 32 + (2 * (data_len)); /* FIXME: We allocate more than we need here */
|
||||
tmp_data = emalloc(tmp_data_len);
|
||||
data_len = dbconvert(NULL, coltype, data, data_len, SQLCHAR, tmp_data, -1);
|
||||
|
||||
zv = emalloc(sizeof(zval));
|
||||
ZVAL_STRING(zv, tmp_data);
|
||||
|
||||
efree(tmp_data);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (coltype) {
|
||||
case SQLVARBINARY:
|
||||
case SQLBINARY:
|
||||
case SQLIMAGE:
|
||||
case SQLTEXT:
|
||||
/* FIXME: Above types should be returned as a stream as they can be VERY large */
|
||||
case SQLCHAR:
|
||||
case SQLVARCHAR:
|
||||
tmp_ptr = emalloc(*len + 1);
|
||||
memcpy(tmp_ptr, *ptr, *len);
|
||||
tmp_ptr[*len] = '\0';
|
||||
*ptr = tmp_ptr;
|
||||
break;
|
||||
case SQLMONEY:
|
||||
case SQLMONEY4:
|
||||
case SQLMONEYN: {
|
||||
DBFLT8 money_value;
|
||||
dbconvert(NULL, coltype, *ptr, *len, SQLFLT8, (LPBYTE)&money_value, 8);
|
||||
*len = spprintf(&tmp_ptr, 0, "%.4f", money_value);
|
||||
*ptr = tmp_ptr;
|
||||
break;
|
||||
}
|
||||
case SQLUNIQUE: {
|
||||
*len = 37;
|
||||
tmp_ptr = emalloc(*len + 1);
|
||||
*len = dbconvert(NULL, SQLUNIQUE, *ptr, *len, SQLCHAR, tmp_ptr, *len);
|
||||
php_strtoupper(tmp_ptr, *len);
|
||||
tmp_ptr[36] = '\0';
|
||||
*ptr = tmp_ptr;
|
||||
break;
|
||||
}
|
||||
case SQLDATETIM4:
|
||||
case SQLDATETIME: {
|
||||
DBDATETIME dt;
|
||||
DBDATEREC di;
|
||||
|
||||
dbconvert(H->link, coltype, (BYTE*) *ptr, -1, SQLDATETIME, (LPBYTE) &dt, -1);
|
||||
dbdatecrack(H->link, &di, &dt);
|
||||
|
||||
*len = spprintf((char**) &tmp_ptr, 20, "%d-%02d-%02d %02d:%02d:%02d",
|
||||
#if defined(PHP_DBLIB_IS_MSSQL) || defined(MSDBLIB)
|
||||
di.year, di.month, di.day, di.hour, di.minute, di.second
|
||||
#else
|
||||
di.dateyear, di.datemonth+1, di.datedmonth, di.datehour, di.dateminute, di.datesecond
|
||||
#endif
|
||||
);
|
||||
|
||||
*ptr = (char*) tmp_ptr;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if (dbwillconvert(coltype, SQLCHAR)) {
|
||||
tmp_len = 32 + (2 * (*len)); /* FIXME: We allocate more than we need here */
|
||||
tmp_ptr = emalloc(tmp_len);
|
||||
*len = dbconvert(NULL, coltype, *ptr, *len, SQLCHAR, tmp_ptr, -1);
|
||||
*ptr = tmp_ptr;
|
||||
} else {
|
||||
*len = 0; /* FIXME: Silently fails and returns null on conversion errors */
|
||||
*ptr = NULL;
|
||||
}
|
||||
if (zv != NULL) {
|
||||
*ptr = (char*)zv;
|
||||
*len = sizeof(zval);
|
||||
} else {
|
||||
*ptr = NULL;
|
||||
*len = 0;
|
||||
}
|
||||
|
||||
*caller_frees = 1;
|
||||
@ -335,6 +418,7 @@ static int pdo_dblib_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zva
|
||||
pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
|
||||
pdo_dblib_db_handle *H = S->H;
|
||||
DBTYPEINFO* dbtypeinfo;
|
||||
int coltype;
|
||||
|
||||
if(colno >= stmt->column_count || colno < 0) {
|
||||
return FAILURE;
|
||||
@ -346,14 +430,28 @@ static int pdo_dblib_stmt_get_column_meta(pdo_stmt_t *stmt, zend_long colno, zva
|
||||
|
||||
if(!dbtypeinfo) return FAILURE;
|
||||
|
||||
coltype = dbcoltype(H->link, colno+1);
|
||||
|
||||
add_assoc_long(return_value, "max_length", dbcollen(H->link, colno+1) );
|
||||
add_assoc_long(return_value, "precision", (int) dbtypeinfo->precision );
|
||||
add_assoc_long(return_value, "scale", (int) dbtypeinfo->scale );
|
||||
add_assoc_string(return_value, "column_source", dbcolsource(H->link, colno+1));
|
||||
add_assoc_string(return_value, "native_type", pdo_dblib_get_field_name(dbcoltype(H->link, colno+1)));
|
||||
add_assoc_long(return_value, "native_type_id", dbcoltype(H->link, colno+1));
|
||||
add_assoc_string(return_value, "native_type", pdo_dblib_get_field_name(coltype));
|
||||
add_assoc_long(return_value, "native_type_id", coltype);
|
||||
add_assoc_long(return_value, "native_usertype_id", dbcolutype(H->link, colno+1));
|
||||
|
||||
switch (coltype) {
|
||||
case SQLBIT:
|
||||
case SQLINT1:
|
||||
case SQLINT2:
|
||||
case SQLINT4:
|
||||
add_assoc_long(return_value, "pdo_type", PDO_PARAM_INT);
|
||||
break;
|
||||
default:
|
||||
add_assoc_long(return_value, "pdo_type", PDO_PARAM_STR);
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -37,21 +37,21 @@ array(4) {
|
||||
[0]=>
|
||||
array(1) {
|
||||
["val"]=>
|
||||
string(1) "1"
|
||||
int(1)
|
||||
}
|
||||
[1]=>
|
||||
array(1) {
|
||||
["val"]=>
|
||||
string(1) "2"
|
||||
int(2)
|
||||
}
|
||||
[2]=>
|
||||
array(1) {
|
||||
["val"]=>
|
||||
string(1) "3"
|
||||
int(3)
|
||||
}
|
||||
[3]=>
|
||||
array(1) {
|
||||
["val"]=>
|
||||
string(1) "4"
|
||||
int(4)
|
||||
}
|
||||
}
|
||||
|
@ -30,10 +30,10 @@ array(10) {
|
||||
int(%d)
|
||||
["native_usertype_id"]=>
|
||||
int(%d)
|
||||
["pdo_type"]=>
|
||||
int(2)
|
||||
["name"]=>
|
||||
string(13) "TABLE_CATALOG"
|
||||
["len"]=>
|
||||
int(255)
|
||||
["pdo_type"]=>
|
||||
int(2)
|
||||
}
|
||||
|
@ -23,21 +23,21 @@ array(3) {
|
||||
[0]=>
|
||||
array(2) {
|
||||
["My Field"]=>
|
||||
string(1) "1"
|
||||
int(1)
|
||||
["Another Field"]=>
|
||||
string(11) "test_string"
|
||||
}
|
||||
[1]=>
|
||||
array(2) {
|
||||
["My Field"]=>
|
||||
string(1) "2"
|
||||
int(2)
|
||||
["Another Field"]=>
|
||||
string(11) "test_string"
|
||||
}
|
||||
[2]=>
|
||||
array(2) {
|
||||
["My Field"]=>
|
||||
string(1) "3"
|
||||
int(3)
|
||||
["Another Field"]=>
|
||||
string(11) "test_string"
|
||||
}
|
||||
|
66
ext/pdo_dblib/tests/types.phpt
Normal file
66
ext/pdo_dblib/tests/types.phpt
Normal file
@ -0,0 +1,66 @@
|
||||
--TEST--
|
||||
PDO_DBLIB: Column data types, with or without stringifying
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('pdo_dblib')) die('skip not loaded');
|
||||
require __DIR__ . '/config.inc';
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require __DIR__ . '/config.inc';
|
||||
|
||||
$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],
|
||||
1000 AS [int],
|
||||
CAST(10.5 AS MONEY) AS [money],
|
||||
CAST('1950-01-18 23:00:00' AS SMALLDATETIME) as [smalldatetime],
|
||||
CAST(1 AS BIT) AS [true]
|
||||
";
|
||||
|
||||
$stmt = $db->query($sql);
|
||||
$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['int'] === 1000);
|
||||
var_dump($row['money'] === 10.5);
|
||||
var_dump($row['smalldatetime'] === '1950-01-18 23:00:00');
|
||||
var_dump($row['true'] === 1);
|
||||
|
||||
$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);
|
||||
$stmt = $db->query($sql);
|
||||
$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['int'] === '1000');
|
||||
var_dump($row['money'] === '10.5');
|
||||
var_dump($row['smalldatetime'] === '1950-01-18 23:00:00');
|
||||
var_dump($row['true'] === '1');
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
Loading…
Reference in New Issue
Block a user