diff --git a/cake/libs/model/datasources/dbo/dbo_mssql.php b/cake/libs/model/datasources/dbo/dbo_mssql.php index 81b7b77d9..d8b094498 100644 --- a/cake/libs/model/datasources/dbo/dbo_mssql.php +++ b/cake/libs/model/datasources/dbo/dbo_mssql.php @@ -54,7 +54,7 @@ class DboMssql extends DboSource { * @var string */ var $endQuote = "]"; - /** +/** * Creates a map between field aliases and numeric indexes. Workaround for the * SQL Server driver's 30-character column name limitation. * @@ -139,6 +139,7 @@ class DboMssql extends DboSource { } if (mssql_select_db($config['database'], $this->connection)) { + $this->_execute("SET DATEFORMAT ymd"); $this->connected = true; } return $this->connected; @@ -209,10 +210,10 @@ class DboMssql extends DboSource { $fields[$column[0]['Field']] = array( 'type' => $this->column($column[0]['Type']), 'null' => (strtoupper($column[0]['Null']) == 'YES'), - 'default' => $column[0]['Default'], + 'default' => preg_replace("/^\('(.*)'\)$/", "$1", $column[0]['Default']), 'length' => intval($column[0]['Length']), ); - if ($fields[$column[0]['Field']]['default'] == '(null)') { + if (in_array($fields[$column[0]['Field']]['default'], array('null', '(null)'))) { $fields[$column[0]['Field']]['default'] = null; } } @@ -244,11 +245,6 @@ class DboMssql extends DboSource { case 'boolean': $data = $this->boolean((bool)$data); break; - case 'datetime': - if ($data && (($timestamp = strtotime($data)) !== false)) { - $data = date('Y-m-d\TH:i:s', $timestamp); - } - break; default: if (get_magic_quotes_gpc()) { $data = stripslashes(str_replace("'", "''", $data)); @@ -286,16 +282,23 @@ class DboMssql extends DboSource { $prepend = 'DISTINCT '; $fields[$i] = trim(str_replace('DISTINCT', '', $fields[$i])); } - $dot = strrpos($fields[$i], '.'); $fieldAlias = count($this->__fieldMappings); - if ($dot === false && !preg_match('/\s+AS\s+/i', $fields[$i])) { - $this->__fieldMappings[$alias . '__' . $fieldAlias] = $alias . '.' . $fields[$i]; - $fields[$i] = $this->name($alias) . '.' . $this->name($fields[$i]) . ' AS ' . $this->name($alias . '__' . $fieldAlias); - } elseif (!preg_match('/\s+AS\s+/i', $fields[$i])) { - $build = explode('.', $fields[$i]); - $this->__fieldMappings[$build[0] . '__' . $fieldAlias] = $build[0] . '.' . $build[1]; - $fields[$i] = $this->name($build[0]) . '.' . $this->name($build[1]) . ' AS ' . $this->name($build[0] . '__' . $fieldAlias); + if (!preg_match('/\s+AS\s+/i', $fields[$i])) { + if (strpos($fields[$i], '.') === false) { + $this->__fieldMappings[$alias . '__' . $fieldAlias] = $alias . '.' . $fields[$i]; + $fieldName = $this->name($alias . '.' . $fields[$i]); + $fieldAlias = $this->name($alias . '__' . $fieldAlias); + } else { + $build = explode('.', $fields[$i]); + $this->__fieldMappings[$build[0] . '__' . $fieldAlias] = $fields[$i]; + $fieldName = $this->name($build[0] . '.' . $build[1]); + $fieldAlias = $this->name(preg_replace("/^\[(.+)\]$/", "$1", $build[0]) . '__' . $fieldAlias); + } + if ($model->getColumnType($fields[$i]) == 'datetime') { + $fieldName = "CONVERT(VARCHAR(20), {$fieldName}, 20)"; + } + $fields[$i] = "{$fieldName} AS {$fieldAlias}"; } $fields[$i] = $prepend . $fields[$i]; } @@ -488,6 +491,13 @@ class DboMssql extends DboSource { function renderStatement($type, $data) { if (strtolower($type) == 'select') { extract($data); + $fields = trim($fields); + + if (strpos($limit, 'TOP') !== false && strpos($fields, 'DISTINCT ') === 0) { + $limit = 'DISTINCT ' . trim($limit); + $fields = substr($fields, 9); + } + if (preg_match('/offset\s+([0-9]+)/i', $limit, $offset)) { $limit = preg_replace('/\s*offset.*$/i', '', $limit); preg_match('/top\s+([0-9]+)/i', $limit, $limitVal); @@ -574,7 +584,11 @@ class DboMssql extends DboSource { */ function buildColumn($column) { $result = preg_replace('/(int|integer)\([0-9]+\)/i', '$1', parent::buildColumn($column)); - if (isset($column['null']) && $column['null'] == true) { + $null = ( + (isset($column['null']) && $column['null'] == true) || + (array_key_exists('default', $column) && $column['default'] === null) + ); + if ($null) { $result .= " NULL"; } return $result; diff --git a/cake/libs/model/datasources/dbo_source.php b/cake/libs/model/datasources/dbo_source.php index 888139021..84b1e9bbd 100644 --- a/cake/libs/model/datasources/dbo_source.php +++ b/cake/libs/model/datasources/dbo_source.php @@ -2087,8 +2087,7 @@ class DboSource extends DataSource { */ function buildColumn($column) { $name = $type = null; - $column = array_merge(array('null' => true), $column); - extract($column); + extract(array_merge(array('null' => true), $column)); if (empty($name) || empty($type)) { trigger_error('Column name or type not defined in schema', E_USER_WARNING); diff --git a/cake/tests/cases/libs/model/datasources/dbo/dbo_mssql.test.php b/cake/tests/cases/libs/model/datasources/dbo/dbo_mssql.test.php index 50fe6b839..e53a3dd2d 100644 --- a/cake/tests/cases/libs/model/datasources/dbo/dbo_mssql.test.php +++ b/cake/tests/cases/libs/model/datasources/dbo/dbo_mssql.test.php @@ -155,9 +155,9 @@ class DboMssqlTest extends CakeTestCase { '[MssqlTestModel].[url] AS [MssqlTestModel__12]', '[MssqlTestModel].[email] AS [MssqlTestModel__13]', '[MssqlTestModel].[comments] AS [MssqlTestModel__14]', - '[MssqlTestModel].[last_login] AS [MssqlTestModel__15]', + 'CONVERT(VARCHAR(20), [MssqlTestModel].[last_login], 20) AS [MssqlTestModel__15]', '[MssqlTestModel].[created] AS [MssqlTestModel__16]', - '[MssqlTestModel].[updated] AS [MssqlTestModel__17]' + 'CONVERT(VARCHAR(20), [MssqlTestModel].[updated], 20) AS [MssqlTestModel__17]' ); $this->assertEqual($result, $expected); @@ -180,6 +180,15 @@ class DboMssqlTest extends CakeTestCase { $this->assertEqual($result, $expected); } + function testDistinctWithLimit() { + $this->db->read($this->model, array( + 'fields' => array('DISTINCT MssqlTestModel.city', 'MssqlTestModel.country'), + 'limit' => 5 + )); + $result = $this->db->getLastQuery(); + $this->assertPattern('/^SELECT DISTINCT TOP 5/', $result); + } + function tearDown() { unset($this->model); } diff --git a/cake/tests/fixtures/person_fixture.php b/cake/tests/fixtures/person_fixture.php index 705bf46ca..b955d0de1 100644 --- a/cake/tests/fixtures/person_fixture.php +++ b/cake/tests/fixtures/person_fixture.php @@ -35,11 +35,15 @@ class PersonFixture extends CakeTestFixture { var $name = 'Person'; var $fields = array( - 'id' => array('type'=>'integer', 'null' => false, 'default' => NULL, 'key' => 'primary'), - 'name' => array('type'=>'string', 'null' => false, 'length' => 32), - 'mother_id' => array('type'=>'integer', 'null' => false, 'key' => 'index'), - 'father_id' => array('type'=>'integer', 'null' => false), - 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1), 'mother_id' => array('column' => array('mother_id', 'father_id'), 'unique' => 0))); + 'id' => array('type' => 'integer', 'null' => false, 'key' => 'primary'), + 'name' => array('type' => 'string', 'null' => false, 'length' => 32), + 'mother_id' => array('type' => 'integer', 'null' => false, 'key' => 'index'), + 'father_id' => array('type' => 'integer', 'null' => false), + 'indexes' => array( + 'PRIMARY' => array('column' => 'id', 'unique' => 1), + 'mother_id' => array('column' => array('mother_id', 'father_id'), 'unique' => 0) + ) + ); var $records = array( array('name' => 'person', 'mother_id' => 2, 'father_id' => 3), @@ -48,6 +52,7 @@ class PersonFixture extends CakeTestFixture { array('name' => 'mother - grand mother', 'mother_id' => 0, 'father_id' => 0), array('name' => 'mother - grand father', 'mother_id' => 0, 'father_id' => 0), array('name' => 'father - grand mother', 'mother_id' => 0, 'father_id' => 0), - array('name' => 'father - grand father', 'mother_id' => 0, 'father_id' => 0)); + array('name' => 'father - grand father', 'mother_id' => 0, 'father_id' => 0) + ); } ?> \ No newline at end of file