From a4c269bf622d1365733481213c903e5fbbdf6787 Mon Sep 17 00:00:00 2001 From: Sean Harvey Date: Tue, 12 Jun 2012 12:55:27 +1200 Subject: [PATCH] BUGFIX Fixing date/datetime handling in MSSQLDatabase Fixing the date type to actually be "date", and not "datetime" so that values are returned as "Y-m-d" for dates, and not "Y-m-d H:i:s". Additionally, fixing a case where using the mssql functions would return strange datetime formats. We need the datetime field values in Y-m-d H:i:s. To get this working, we need to inspect the field type when retrieving rows from the database and re-format the datetime value at this point. This is done in MSSQLQuery::nextRecord() --- code/MSSQLDatabase.php | 18 +++++++++++++++--- tests/MSSQLDatabaseQueryTest.php | 28 ++++++++++++++++++++++++++++ tests/MSSQLDatabaseQueryTest.yml | 5 +++++ 3 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 tests/MSSQLDatabaseQueryTest.php create mode 100644 tests/MSSQLDatabaseQueryTest.yml diff --git a/code/MSSQLDatabase.php b/code/MSSQLDatabase.php index 356b244..97ba257 100644 --- a/code/MSSQLDatabase.php +++ b/code/MSSQLDatabase.php @@ -983,7 +983,7 @@ class MSSQLDatabase extends SS_Database { * @return string */ public function date($values) { - return 'datetime null'; + return 'date null'; } /** @@ -1221,7 +1221,6 @@ class MSSQLDatabase extends SS_Database { $text = 'DELETE '; } else { $distinct = $query->getDistinct() ? 'DISTINCT ' : ''; - // If there's a limit but no offset, just use 'TOP X' // rather than the more complex sub-select method if ($limit != 0 && $offset == 0) { @@ -1775,7 +1774,20 @@ class MSSQLQuery extends SS_Query { if(!is_resource($this->handle)) return false; if($this->mssql) { - if($data = mssql_fetch_assoc($this->handle)) { + if($row = mssql_fetch_row($this->handle)) { + foreach($row as $i => $value) { + $field = mssql_fetch_field($this->handle, $i); + + // fix datetime formatting from format "Jan 1 2012 12:00:00:000AM" to "2012-01-01 12:00:00" + // strtotime doesn't understand this format, so we need to do some modification of the value first + if($field->type == 'datetime' && $value) { + $value = date('Y-m-d H:i:s', strtotime(preg_replace('/:[0-9][0-9][0-9]([ap]m)$/i', ' \\1', $value))); + } + + if(isset($value) || !isset($data[$field->name])) { + $data[$field->name] = $value; + } + } return $data; } } else { diff --git a/tests/MSSQLDatabaseQueryTest.php b/tests/MSSQLDatabaseQueryTest.php new file mode 100644 index 0000000..a5bc6a9 --- /dev/null +++ b/tests/MSSQLDatabaseQueryTest.php @@ -0,0 +1,28 @@ +objFromFixture('MSSQLDatabaseQueryTestDataObject', 'test-data-1'); + $this->assertEquals('2012-01-01', $obj->TestDate, 'Date field value is formatted correctly (Y-m-d)'); + } + + public function testDatetimeValueFormatting() { + $obj = $this->objFromFixture('MSSQLDatabaseQueryTestDataObject', 'test-data-1'); + $this->assertEquals('2012-01-01 10:30:00', $obj->TestDatetime, 'Datetime field value is formatted correctly (Y-m-d H:i:s)'); + } + +} +class MSSQLDatabaseQueryTestDataObject extends DataObject implements TestOnly { + + public static $db = array( + 'TestDate' => 'Date', + 'TestDatetime' => 'SS_Datetime' + ); + +} diff --git a/tests/MSSQLDatabaseQueryTest.yml b/tests/MSSQLDatabaseQueryTest.yml new file mode 100644 index 0000000..42abb06 --- /dev/null +++ b/tests/MSSQLDatabaseQueryTest.yml @@ -0,0 +1,5 @@ +MSSQLDatabaseQueryTestDataObject: + test-data-1: + TestDate: 2012-01-01 + TestDatetime: 2012-01-01 10:30:00 +