diff options
author | fandrieu <fandrieu@gmail.com> | 2017-10-31 17:33:10 -0400 |
---|---|---|
committer | Adam Baratz <adambaratz@php.net> | 2017-10-31 17:52:59 -0400 |
commit | b72af30a534fb3ff2f899f1561fd021bdbc832e1 (patch) | |
tree | 7ba563ec3fa9494535f0f6721e6f56d70c82409e /ext | |
parent | 2ecfcdaf1b94868756cabbbb2c33276f823dafd7 (diff) | |
download | php-git-b72af30a534fb3ff2f899f1561fd021bdbc832e1.tar.gz |
Fix #74243: allow locales.conf to drive datetime format
Add a driver attribute, PDO::DBLIB_ATTR_DATETIME_CONVERT, to control.
Diffstat (limited to 'ext')
-rw-r--r-- | ext/pdo_dblib/dblib_driver.c | 9 | ||||
-rw-r--r-- | ext/pdo_dblib/dblib_stmt.c | 79 | ||||
-rw-r--r-- | ext/pdo_dblib/pdo_dblib.c | 1 | ||||
-rw-r--r-- | ext/pdo_dblib/php_pdo_dblib_int.h | 2 | ||||
-rw-r--r-- | ext/pdo_dblib/tests/datetime_convert.phpt | 36 |
5 files changed, 100 insertions, 27 deletions
diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c index e8c010c563..f66e83734c 100644 --- a/ext/pdo_dblib/dblib_driver.c +++ b/ext/pdo_dblib/dblib_driver.c @@ -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); diff --git a/ext/pdo_dblib/dblib_stmt.c b/ext/pdo_dblib/dblib_stmt.c index 2cebe982e4..175cb30332 100644 --- a/ext/pdo_dblib/dblib_stmt.c +++ b/ext/pdo_dblib/dblib_stmt.c @@ -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) { diff --git a/ext/pdo_dblib/pdo_dblib.c b/ext/pdo_dblib/pdo_dblib.c index d6a0eda07b..98e21c9d86 100644 --- a/ext/pdo_dblib/pdo_dblib.c +++ b/ext/pdo_dblib/pdo_dblib.c @@ -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; diff --git a/ext/pdo_dblib/php_pdo_dblib_int.h b/ext/pdo_dblib/php_pdo_dblib_int.h index 1b59dd3a38..805435a1c2 100644 --- a/ext/pdo_dblib/php_pdo_dblib_int.h +++ b/ext/pdo_dblib/php_pdo_dblib_int.h @@ -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 diff --git a/ext/pdo_dblib/tests/datetime_convert.phpt b/ext/pdo_dblib/tests/datetime_convert.phpt new file mode 100644 index 0000000000..13f7db2f0b --- /dev/null +++ b/ext/pdo_dblib/tests/datetime_convert.phpt @@ -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" +} |