Correcting MSSQL limit/distinct handling, correcting date/time handling, fixes #4352, fixes #1778

git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6748 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
nate 2008-05-03 14:15:47 +00:00
parent ce31e77574
commit 32ea41a90e
4 changed files with 54 additions and 27 deletions

View file

@ -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])) {
if (!preg_match('/\s+AS\s+/i', $fields[$i])) {
if (strpos($fields[$i], '.') === false) {
$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])) {
$fieldName = $this->name($alias . '.' . $fields[$i]);
$fieldAlias = $this->name($alias . '__' . $fieldAlias);
} else {
$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);
$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;

View file

@ -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);

View file

@ -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);
}

View file

@ -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)
);
}
?>