Add a driver attribute, PDO::DBLIB_ATTR_DATETIME_CONVERT, to control.
- 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
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;
}
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;
}
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;
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);
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)
{
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) {
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;
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 {
PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER,
PDO_DBLIB_ATTR_VERSION,
PDO_DBLIB_ATTR_SKIP_EMPTY_ROWSETS,
+ PDO_DBLIB_ATTR_DATETIME_CONVERT,
};
#endif
--- /dev/null
+--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"
+}