1
0
mirror of https://github.com/php/php-src.git synced 2026-03-29 03:32:20 +02:00

Fix #74243: allow locales.conf to drive datetime format

Add a driver attribute, PDO::DBLIB_ATTR_DATETIME_CONVERT, to control.
This commit is contained in:
fandrieu
2017-10-31 17:33:10 -04:00
committed by Adam Baratz
parent 2ecfcdaf1b
commit b72af30a53
6 changed files with 101 additions and 27 deletions

1
NEWS
View File

@@ -79,6 +79,7 @@ PHP NEWS
- PDO_DBlib:
. Implemented request #69592 (allow 0-column rowsets to be skipped
automatically). (fandrieu)
. Fixed bug #74243 (allow locales.conf to drive datetime format). (fandrieu)
- PDO_OCI:
. Fixed bug #74631 (PDO_PCO with PHP-FPM: OCI environment initialized

View File

@@ -290,6 +290,9 @@ static int dblib_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
case PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS:
H->skip_empty_rowsets = zval_is_true(val);
return 1;
case PDO_DBLIB_ATTR_DATETIME_CONVERT:
H->datetime_convert = zval_get_long(val);
return 1;
default:
return 0;
}
@@ -321,6 +324,10 @@ static int dblib_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_valu
ZVAL_BOOL(return_value, H->skip_empty_rowsets);
break;
case PDO_DBLIB_ATTR_DATETIME_CONVERT:
ZVAL_BOOL(return_value, H->datetime_convert);
break;
default:
return 0;
}
@@ -395,6 +402,7 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
H->assume_national_character_set_strings = 0;
H->stringify_uniqueidentifier = 0;
H->skip_empty_rowsets = 0;
H->datetime_convert = 0;
if (!H->login) {
goto cleanup;
@@ -418,6 +426,7 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
H->assume_national_character_set_strings = pdo_attr_lval(driver_options, PDO_ATTR_DEFAULT_STR_PARAM, 0) == PDO_PARAM_STR_NATL ? 1 : 0;
H->stringify_uniqueidentifier = pdo_attr_lval(driver_options, PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER, 0);
H->skip_empty_rowsets = pdo_attr_lval(driver_options, PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS, 0);
H->datetime_convert = pdo_attr_lval(driver_options, PDO_DBLIB_ATTR_DATETIME_CONVERT, 0);
}
DBERRHANDLE(H->login, (EHANDLEFUNC) pdo_dblib_error_handler);

View File

@@ -260,6 +260,51 @@ static int pdo_dblib_stmt_describe(pdo_stmt_t *stmt, int colno)
return 1;
}
static int pdo_dblib_stmt_stringify_col(pdo_stmt_t *stmt, int coltype)
{
pdo_dblib_stmt *S = (pdo_dblib_stmt*)stmt->driver_data;
pdo_dblib_db_handle *H = S->H;
switch (coltype) {
case SQLDECIMAL:
case SQLNUMERIC:
case SQLMONEY:
case SQLMONEY4:
case SQLMONEYN:
case SQLFLT4:
case SQLFLT8:
case SQLINT4:
case SQLINT2:
case SQLINT1:
case SQLBIT:
if (stmt->dbh->stringify) {
return 1;
}
break;
case SQLINT8:
if (stmt->dbh->stringify) {
return 1;
}
/* force stringify if DBBIGINT won't fit in zend_long */
/* this should only be an issue for 32-bit machines */
if (sizeof(zend_long) < sizeof(DBBIGINT)) {
return 1;
}
break;
case SQLDATETIME:
case SQLDATETIM4:
if (H->datetime_convert) {
return 1;
}
break;
}
return 0;
}
static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
zend_ulong *len, int *caller_frees)
{
@@ -278,35 +323,15 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
data_len = dbdatlen(H->link, colno+1);
if (data_len != 0 || data != NULL) {
/* force stringify if DBBIGINT won't fit in zend_long */
/* this should only be an issue for 32-bit machines */
if (stmt->dbh->stringify || (coltype == SQLINT8 && sizeof(zend_long) < sizeof(DBBIGINT))) {
switch (coltype) {
case SQLDECIMAL:
case SQLNUMERIC:
case SQLMONEY:
case SQLMONEY4:
case SQLMONEYN:
case SQLFLT4:
case SQLFLT8:
case SQLINT8:
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, (LPBYTE) tmp_data, -1);
if (pdo_dblib_stmt_stringify_col(stmt, coltype) && 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, (LPBYTE) tmp_data, -1);
zv = emalloc(sizeof(zval));
ZVAL_STRING(zv, tmp_data);
zv = emalloc(sizeof(zval));
ZVAL_STRING(zv, tmp_data);
efree(tmp_data);
}
break;
}
}
efree(tmp_data);
}
if (!zv) {

View File

@@ -196,6 +196,7 @@ PHP_MINIT_FUNCTION(pdo_dblib)
REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER", (long) PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER);
REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_VERSION", (long) PDO_DBLIB_ATTR_VERSION);
REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_SKIP_EMPTY_ROWSETS", (long) PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS);
REGISTER_PDO_CLASS_CONST_LONG("DBLIB_ATTR_DATETIME_CONVERT", (long) PDO_DBLIB_ATTR_DATETIME_CONVERT);
if (FAIL == dbinit()) {
return FAILURE;

View File

@@ -119,6 +119,7 @@ typedef struct {
unsigned assume_national_character_set_strings:1;
unsigned stringify_uniqueidentifier:1;
unsigned skip_empty_rowsets:1;
unsigned datetime_convert:1;
} pdo_dblib_db_handle;
typedef struct {
@@ -152,6 +153,7 @@ enum {
PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER,
PDO_DBLIB_ATTR_VERSION,
PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS,
PDO_DBLIB_ATTR_DATETIME_CONVERT,
};
#endif

View File

@@ -0,0 +1,36 @@
--TEST--
PDO_DBLIB: PDO::DBLIB_ATTR_DATETIME_CONVERT
--SKIPIF--
<?php
if (!extension_loaded('pdo_dblib')) die('skip not loaded');
require __DIR__ . '/config.inc';
?>
--FILE--
<?php
require __DIR__ . '/config.inc';
$sql = "SELECT convert(datetime, '20171027 10:22:44.135') AS [d]";
var_dump($db->getAttribute(PDO::DBLIB_ATTR_DATETIME_CONVERT));
$stmt = $db->query($sql);
var_dump($stmt->fetch(PDO::FETCH_ASSOC));
// assume default date format: %b %e %Y %I:%M:%S:%z%p
$db->setAttribute(PDO::DBLIB_ATTR_DATETIME_CONVERT, 1);
var_dump($db->getAttribute(PDO::DBLIB_ATTR_DATETIME_CONVERT));
$stmt = $db->query($sql);
var_dump($stmt->fetch(PDO::FETCH_ASSOC));
?>
--EXPECT--
bool(false)
array(1) {
["d"]=>
string(19) "2017-10-27 10:22:44"
}
bool(true)
array(1) {
["d"]=>
string(26) "Oct 27 2017 10:22:44:137AM"
}