summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorfandrieu <fandrieu@gmail.com>2017-10-31 17:33:10 -0400
committerAdam Baratz <adambaratz@php.net>2017-10-31 17:52:59 -0400
commitb72af30a534fb3ff2f899f1561fd021bdbc832e1 (patch)
tree7ba563ec3fa9494535f0f6721e6f56d70c82409e /ext
parent2ecfcdaf1b94868756cabbbb2c33276f823dafd7 (diff)
downloadphp-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.c9
-rw-r--r--ext/pdo_dblib/dblib_stmt.c79
-rw-r--r--ext/pdo_dblib/pdo_dblib.c1
-rw-r--r--ext/pdo_dblib/php_pdo_dblib_int.h2
-rw-r--r--ext/pdo_dblib/tests/datetime_convert.phpt36
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"
+}