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:
1
NEWS
1
NEWS
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
36
ext/pdo_dblib/tests/datetime_convert.phpt
Normal file
36
ext/pdo_dblib/tests/datetime_convert.phpt
Normal 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"
|
||||
}
|
||||
Reference in New Issue
Block a user