Refactoring DboSource - removes all SQL from Model, refactoring transaction handling

git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@6557 3807eeeb-6ff5-0310-8944-8be069107fe0
This commit is contained in:
nate 2008-03-11 02:44:33 +00:00
parent d326c6eefe
commit c1c35b2e13
11 changed files with 278 additions and 390 deletions

View file

@ -782,7 +782,8 @@ class TreeBehavior extends ModelBehavior {
* @access private * @access private
*/ */
function __getMax($model, $scope, $right) { function __getMax($model, $scope, $right) {
list($edge) = array_values($model->find('first', array('conditions' => $scope, 'fields' => 'MAX(' . $right . ') AS ' . $right, 'recursive' => -1))); $db =& ConnectionManager::getDataSource($model->useDbConfig);
list($edge) = array_values($model->find('first', array('conditions' => $scope, 'fields' => $db->calculate('max', array($right)), 'recursive' => -1)));
return ife(empty ($edge[$right]), 0, $edge[$right]); return ife(empty ($edge[$right]), 0, $edge[$right]);
} }
/** /**

View file

@ -252,7 +252,7 @@ class DataSource extends Object {
* @return boolean True * @return boolean True
*/ */
function begin() { function begin() {
return true; return !$this->_transactionStarted;
} }
/** /**
* Commit a transaction * Commit a transaction
@ -260,7 +260,7 @@ class DataSource extends Object {
* @return boolean True * @return boolean True
*/ */
function commit(&$model) { function commit(&$model) {
return true; return $this->_transactionStarted;
} }
/** /**
* Rollback a transaction * Rollback a transaction
@ -268,7 +268,7 @@ class DataSource extends Object {
* @return boolean True * @return boolean True
*/ */
function rollback(&$model) { function rollback(&$model) {
return true; return $this->_transactionStarted;
} }
/** /**
* Converts column types to basic types * Converts column types to basic types
@ -499,6 +499,10 @@ class DataSource extends Object {
* *
*/ */
function __destruct() { function __destruct() {
if ($this->_transactionStarted) {
$null = null;
$this->rollback($null);
}
if ($this->connected) { if ($this->connected) {
$this->close(); $this->close();
} }

View file

@ -301,40 +301,9 @@ class DboMssql extends DboSource {
* (i.e. if the database/model does not support transactions). * (i.e. if the database/model does not support transactions).
*/ */
function begin(&$model) { function begin(&$model) {
if (parent::begin($model)) { if (parent::begin($model) && $this->execute('BEGIN TRANSACTION')) {
if ($this->execute('BEGIN TRANSACTION')) { $this->_transactionStarted = true;
$this->_transactionStarted = true; return true;
return true;
}
}
return false;
}
/**
* Commit a transaction
*
* @param unknown_type $model
* @return boolean True on success, false on fail
* (i.e. if the database/model does not support transactions,
* or a transaction has not started).
*/
function commit(&$model) {
if (parent::commit($model)) {
$this->_transactionStarted = false;
return $this->execute('COMMIT');
}
return false;
}
/**
* Rollback a transaction
*
* @param unknown_type $model
* @return boolean True on success, false on fail
* (i.e. if the database/model does not support transactions,
* or a transaction has not started).
*/
function rollback(&$model) {
if (parent::rollback($model)) {
return $this->execute('ROLLBACK');
} }
return false; return false;
} }

View file

@ -253,40 +253,9 @@ class DboMysqli extends DboSource {
* (i.e. if the database/model does not support transactions). * (i.e. if the database/model does not support transactions).
*/ */
function begin(&$model) { function begin(&$model) {
if (parent::begin($model)) { if (parent::begin($model) && $this->execute('START TRANSACTION')) {
if ($this->execute('START TRANSACTION')) { $this->_transactionStarted = true;
$this->_transactionStarted = true; return true;
return true;
}
}
return false;
}
/**
* Commit a transaction
*
* @param unknown_type $model
* @return boolean True on success, false on fail
* (i.e. if the database/model does not support transactions,
* or a transaction has not started).
*/
function commit(&$model) {
if (parent::commit($model)) {
$this->_transactionStarted = false;
return $this->execute('COMMIT');
}
return false;
}
/**
* Rollback a transaction
*
* @param unknown_type $model
* @return boolean True on success, false on fail
* (i.e. if the database/model does not support transactions,
* or a transaction has not started).
*/
function rollback(&$model) {
if (parent::rollback($model)) {
return $this->execute('ROLLBACK');
} }
return false; return false;
} }

View file

@ -84,34 +84,36 @@ class DboPostgres extends DboSource {
* @return True if successfully connected. * @return True if successfully connected.
*/ */
function connect() { function connect() {
$config = $this->config; $config = $this->config;
$connect = $config['connect']; $connect = $config['connect'];
$this->connection = $connect("host='{$config['host']}' port='{$config['port']}' dbname='{$config['database']}' user='{$config['login']}' password='{$config['password']}'"); $this->connection = $connect("host='{$config['host']}' port='{$config['port']}' dbname='{$config['database']}' user='{$config['login']}' password='{$config['password']}'");
$this->connected = false;
if ($this->connection) { if ($this->connection) {
$this->connected = true; $this->connected = true;
$this->_execute("SET search_path TO " . $config['schema']); $this->_execute("SET search_path TO " . $config['schema']);
} else {
$this->connected = false;
} }
if (!empty($config['encoding'])) { if (!empty($config['encoding'])) {
$this->setEncoding($config['encoding']); $this->setEncoding($config['encoding']);
} }
return $this->connected; return $this->connected;
} }
/** /**
* Disconnects from database. * Disconnects from database.
* *
* @return boolean True if the database could be disconnected, else false * @return boolean True if the database could be disconnected, else false
*/ */
function disconnect() { function disconnect() {
@pg_free_result($this->results); if (is_resource($this->results)) {
$this->connected = !@pg_close($this->connection); pg_free_result($this->results);
}
if (is_resource($this->connected)) {
$this->connected = !pg_close($this->connection);
} else {
$this->connected = false;
}
return !$this->connected; return !$this->connected;
} }
/** /**
* Executes given SQL statement. * Executes given SQL statement.
* *
@ -265,55 +267,21 @@ class DboPostgres extends DboSource {
* (i.e. if the database/model does not support transactions). * (i.e. if the database/model does not support transactions).
*/ */
function begin(&$model) { function begin(&$model) {
if (parent::begin($model)) { if (parent::begin($model) && $this->execute('BEGIN')) {
if ($this->execute('BEGIN')) { $this->_transactionStarted = true;
$this->_transactionStarted = true; return true;
return true;
}
} }
return false; return false;
} }
/**
* Commit a transaction
*
* @param unknown_type $model
* @return boolean True on success, false on fail
* (i.e. if the database/model does not support transactions,
* or a transaction has not started).
*/
function commit(&$model) {
if (parent::commit($model)) {
$this->_transactionStarted = false;
return $this->execute('COMMIT');
}
return false;
}
/**
* Rollback a transaction
*
* @param unknown_type $model
* @return boolean True on success, false on fail
* (i.e. if the database/model does not support transactions,
* or a transaction has not started).
*/
function rollback(&$model) {
if (parent::rollback($model)) {
return $this->execute('ROLLBACK');
}
return false;
}
/** /**
* Returns a formatted error message from previous database operation. * Returns a formatted error message from previous database operation.
* *
* @return string Error message * @return string Error message
*/ */
function lastError() { function lastError() {
$last_error = pg_last_error($this->connection); $error = pg_last_error($this->connection);
if ($last_error) { if ($error) {
return $last_error; return $error;
} }
return null; return null;
} }

View file

@ -534,7 +534,7 @@ class DboSource extends DataSource {
*/ */
function read(&$model, $queryData = array(), $recursive = null) { function read(&$model, $queryData = array(), $recursive = null) {
$this->__scrubQueryData($queryData); $queryData = $this->__scrubQueryData($queryData);
$null = null; $null = null;
$array = array(); $array = array();
$linkedModels = array(); $linkedModels = array();
@ -561,18 +561,12 @@ class DboSource extends DataSource {
foreach ($model->{$type} as $assoc => $assocData) { foreach ($model->{$type} as $assoc => $assocData) {
if ($model->recursive > -1) { if ($model->recursive > -1) {
$linkModel =& $model->{$assoc}; $linkModel =& $model->{$assoc};
$external = isset($assocData['external']); $external = isset($assocData['external']);
if ($model->alias == $linkModel->alias && $type != 'hasAndBelongsToMany' && $type != 'hasMany') {
if (true === $this->generateSelfAssociationQuery($model, $linkModel, $type, $assoc, $assocData, $queryData, $external, $null)) { if ($model->useDbConfig == $linkModel->useDbConfig) {
if (true === $this->generateAssociationQuery($model, $linkModel, $type, $assoc, $assocData, $queryData, $external, $null)) {
$linkedModels[] = $type . '/' . $assoc; $linkedModels[] = $type . '/' . $assoc;
} }
} else {
if ($model->useDbConfig == $linkModel->useDbConfig) {
if (true === $this->generateAssociationQuery($model, $linkModel, $type, $assoc, $assocData, $queryData, $external, $null)) {
$linkedModels[] = $type . '/' . $assoc;
}
}
} }
} }
} }
@ -923,105 +917,21 @@ class DboSource extends DataSource {
} }
} }
/** /**
* Enter description here... * Generates an array representing a query or part of a query from a single model or two associated models
*
* @param unknown_type $model
* @param unknown_type $linkModel
* @param unknown_type $type
* @param unknown_type $association
* @param unknown_type $assocData
* @param unknown_type $queryData
* @param unknown_type $external
* @param unknown_type $resultSet
* @return unknown
*/
function generateSelfAssociationQuery(&$model, &$linkModel, $type, $association = null, $assocData = array(), &$queryData, $external = false, &$resultSet) {
$alias = $association;
if (empty($alias) && !empty($linkModel)) {
$alias = $linkModel->alias;
}
if (!isset($queryData['selfJoin'])) {
$queryData['selfJoin'] = array();
$self = array(
'fields' => $this->fields($model, null, $queryData['fields']),
'joins' => array(array(
'table' => $this->fullTableName($linkModel),
'alias' => $alias,
'type' => 'LEFT',
'conditions' => array(
$model->escapeField($assocData['foreignKey']) => '{$__cakeIdentifier[' . "{$alias}.{$linkModel->primaryKey}" . ']__$}'))
),
'table' => $this->fullTableName($model),
'alias' => $model->alias,
'limit' => $queryData['limit'],
'offset' => $queryData['offset'],
'conditions'=> $queryData['conditions'],
'order' => $queryData['order']
);
if (isset($assocData['type'])) {
$self['joins'][0]['type'] = $assocData['type'];
}
if (!empty($assocData['conditions'])) {
$self['joins'][0]['conditions'] = trim($this->conditions(array_merge($self['joins'][0]['conditions'], (array)$assocData['conditions']), true, false));
}
if (!empty($queryData['joins'])) {
foreach ($queryData['joins'] as $join) {
$self['joins'][] = $join;
}
}
if ($this->__bypass === false) {
$self['fields'] = array_merge($self['fields'], $this->fields($linkModel, $alias, (isset($assocData['fields']) ? $assocData['fields'] : '')));
}
if (!in_array($self, $queryData['selfJoin'])) {
$queryData['selfJoin'][] = $self;
return true;
}
} elseif (isset($linkModel)) {
return $this->generateAssociationQuery($model, $linkModel, $type, $association, $assocData, $queryData, $external, $resultSet);
} else {
$result = $queryData['selfJoin'][0];
if (!empty($queryData['joins'])) {
foreach ($queryData['joins'] as $join) {
if (!in_array($join, $result['joins'])) {
$result['joins'][] = $join;
}
}
}
if (!empty($queryData['conditions'])) {
$result['conditions'] = trim($this->conditions(array_merge($result['conditions'], $assocData['conditions']), true, false));
}
if (!empty($queryData['fields'])) {
$result['fields'] = array_unique(array_merge($result['fields'], $queryData['fields']));
}
$sql = $this->buildStatement($result, $model);
return $sql;
}
}
/**
* Enter description here...
* *
* @param Model $model * @param Model $model
* @param unknown_type $linkModel * @param Model $linkModel
* @param unknown_type $type * @param string $type
* @param unknown_type $association * @param string $association
* @param unknown_type $assocData * @param array $assocData
* @param unknown_type $queryData * @param array $queryData
* @param unknown_type $external * @param boolean $external
* @param unknown_type $resultSet * @param array $resultSet
* @return unknown * @return mixed
*/ */
function generateAssociationQuery(&$model, &$linkModel, $type, $association = null, $assocData = array(), &$queryData, $external = false, &$resultSet) { function generateAssociationQuery(&$model, &$linkModel, $type, $association = null, $assocData = array(), &$queryData, $external = false, &$resultSet) {
$this->__scrubQueryData($queryData); $queryData = $this->__scrubQueryData($queryData);
$this->__scrubQueryData($assocData); $assocData = $this->__scrubQueryData($assocData);
$joinedOnSelf = false;
if (empty($queryData['fields'])) { if (empty($queryData['fields'])) {
$queryData['fields'] = $this->fields($model, $model->alias); $queryData['fields'] = $this->fields($model, $model->alias);
@ -1033,21 +943,19 @@ class DboSource extends DataSource {
$match = strpos($passedFields[0], $assocFields[0]); $match = strpos($passedFields[0], $assocFields[0]);
$match1 = strpos($passedFields[0], 'COUNT('); $match1 = strpos($passedFields[0], 'COUNT(');
if ($match === false && $match1 === false) { if ($match === false && $match1 === false) {
$queryData['fields'] = array_unique(array_merge($passedFields, $assocFields)); $queryData['fields'] = array_merge($passedFields, $assocFields);
} else { } else {
$queryData['fields'] = $passedFields; $queryData['fields'] = $passedFields;
} }
} else { } else {
$queryData['fields'] = array_unique(array_merge($passedFields, $assocFields)); $queryData['fields'] = array_merge($passedFields, $assocFields);
} }
unset($assocFields, $passedFields); unset($assocFields, $passedFields);
} }
if ($linkModel == null) { if ($linkModel == null) {
if (array_key_exists('selfJoin', $queryData)) { return $this->buildStatement(
return $this->generateSelfAssociationQuery($model, $linkModel, $type, $association, $assocData, $queryData, $external, $resultSet); array(
} else {
return $this->buildStatement(array(
'fields' => array_unique($queryData['fields']), 'fields' => array_unique($queryData['fields']),
'table' => $this->fullTableName($model), 'table' => $this->fullTableName($model),
'alias' => $model->alias, 'alias' => $model->alias,
@ -1055,44 +963,33 @@ class DboSource extends DataSource {
'offset' => $queryData['offset'], 'offset' => $queryData['offset'],
'joins' => $queryData['joins'], 'joins' => $queryData['joins'],
'conditions' => $queryData['conditions'], 'conditions' => $queryData['conditions'],
'order' => $queryData['order']), $model 'order' => $queryData['order']
); ),
} $model
);
} }
if ($external && !empty($assocData['finderQuery'])) {
return $assocData['finderQuery'];
}
$alias = $association; $alias = $association;
$self = ($model->name == $linkModel->name);
if ($model->alias == $linkModel->alias) { $fields = array();
$joinedOnSelf = true;
}
if ($external && isset($assocData['finderQuery'])) {
if (!empty($assocData['finderQuery'])) {
return $assocData['finderQuery'];
}
}
if ((!$external && in_array($type, array('hasOne', 'belongsTo')) && $this->__bypass === false) || $external) { if ((!$external && in_array($type, array('hasOne', 'belongsTo')) && $this->__bypass === false) || $external) {
$fields = $this->fields($linkModel, $alias, $assocData['fields']); $fields = $this->fields($linkModel, $alias, $assocData['fields']);
} else {
$fields = array();
} }
$limit = ''; if (empty($assocData['offset']) && !empty($assocData['page'])) {
$assocData['offset'] = ($assocData['page'] - 1) * $assocData['limit'];
if (isset($assocData['limit'])) {
if ((!isset($assocData['offset']) || (empty($assocData['offset']))) && isset($assocData['page'])) {
$assocData['offset'] = ($assocData['page'] - 1) * $assocData['limit'];
} elseif (!isset($assocData['offset'])) {
$assocData['offset'] = null;
}
$limit = $this->limit($assocData['limit'], $assocData['offset']);
} }
$assocData['limit'] = $this->limit($assocData['limit'], $assocData['offset']);
switch($type) { switch($type) {
case 'hasOne': case 'hasOne':
case 'belongsTo': case 'belongsTo':
$conditions = $this->__mergeConditions( $conditions = $this->__mergeConditions(
$assocData['conditions'], $assocData['conditions'],
$this->getConstraint($type, $model, $linkModel, $alias, array_merge($assocData, compact('external'))) $this->getConstraint($type, $model, $linkModel, $alias, array_merge($assocData, compact('external', 'self')))
); );
if ($external) { if ($external) {
$query = array_merge($assocData, array( $query = array_merge($assocData, array(
@ -1101,22 +998,14 @@ class DboSource extends DataSource {
'fields' => $fields, 'fields' => $fields,
'alias' => $alias 'alias' => $alias
)); ));
$query = array_merge(array('order' => $assocData['order'], 'limit' => $assocData['limit']), $query);
if ($type == 'belongsTo') {
// Dunno if we should be doing this for hasOne also...?
// Or maybe not doing it at all...?
$query = array_merge($query, array('order' => $assocData['order'], 'limit' => $limit));
}
} else { } else {
$join = array( $join = array(
'table' => $this->fullTableName($linkModel), 'table' => $this->fullTableName($linkModel),
'alias' => $alias, 'alias' => $alias,
'type' => 'LEFT', 'type' => isset($assocData['type']) ? $assocData['type'] : 'LEFT',
'conditions' => trim($this->conditions($conditions, true, false)) 'conditions' => trim($this->conditions($conditions, true, false))
); );
if (isset($assocData['type'])) {
$join['type'] = $assocData['type'];
}
$queryData['fields'] = array_merge($queryData['fields'], $fields); $queryData['fields'] = array_merge($queryData['fields'], $fields);
if (!empty($assocData['order'])) { if (!empty($assocData['order'])) {
@ -1131,17 +1020,15 @@ class DboSource extends DataSource {
case 'hasMany': case 'hasMany':
$assocData['fields'] = $this->fields($linkModel, $alias, $assocData['fields']); $assocData['fields'] = $this->fields($linkModel, $alias, $assocData['fields']);
if (!empty($assocData['foreignKey'])) { if (!empty($assocData['foreignKey'])) {
$assocData['fields'] = array_unique(array_merge( $assocData['fields'] = array_merge($assocData['fields'], $this->fields($linkModel, $alias, array("{$alias}.{$assocData['foreignKey']}")));
$assocData['fields'], $this->fields($linkModel, $alias, array("{$alias}.{$assocData['foreignKey']}"))
));
} }
$query = array( $query = array(
'conditions' => $this->__mergeConditions($this->getConstraint('hasMany', $model, $linkModel, $alias, $assocData), $assocData['conditions']), 'conditions' => $this->__mergeConditions($this->getConstraint('hasMany', $model, $linkModel, $alias, $assocData), $assocData['conditions']),
'fields' => $assocData['fields'], 'fields' => array_unique($assocData['fields']),
'table' => $this->fullTableName($linkModel), 'table' => $this->fullTableName($linkModel),
'alias' => $alias, 'alias' => $alias,
'order' => $assocData['order'], 'order' => $assocData['order'],
'limit' => $limit 'limit' => $assocData['limit']
); );
break; break;
case 'hasAndBelongsToMany': case 'hasAndBelongsToMany':
@ -1164,7 +1051,7 @@ class DboSource extends DataSource {
$query = array( $query = array(
'conditions' => $assocData['conditions'], 'conditions' => $assocData['conditions'],
'limit' => $limit, 'limit' => $assocData['limit'],
'table' => $this->fullTableName($linkModel), 'table' => $this->fullTableName($linkModel),
'alias' => $alias, 'alias' => $alias,
'fields' => array_merge($this->fields($linkModel, $alias, $assocData['fields']), $joinFields), 'fields' => array_merge($this->fields($linkModel, $alias, $assocData['fields']), $joinFields),
@ -1191,7 +1078,7 @@ class DboSource extends DataSource {
* @return array Conditions array defining the constraint between $model and $association * @return array Conditions array defining the constraint between $model and $association
*/ */
function getConstraint($type, $model, $linkModel, $alias, $assoc, $alias2 = null) { function getConstraint($type, $model, $linkModel, $alias, $assoc, $alias2 = null) {
$assoc = array_merge(array('external' => false), $assoc); $assoc = array_merge(array('external' => false, 'self' => false), $assoc);
if (array_key_exists('foreignKey', $assoc) && empty($assoc['foreignKey'])) { if (array_key_exists('foreignKey', $assoc) && empty($assoc['foreignKey'])) {
return array(); return array();
@ -1459,20 +1346,42 @@ class DboSource extends DataSource {
foreach ($joins as $assoc) { foreach ($joins as $assoc) {
if (isset($model->{$assoc}) && $model->useDbConfig == $model->{$assoc}->useDbConfig) { if (isset($model->{$assoc}) && $model->useDbConfig == $model->{$assoc}->useDbConfig) {
$assocData = $model->getAssociated($assoc); $assocData = $model->getAssociated($assoc);
$type = 'LEFT';
if (isset($assocData['type'])) {
$type = $assocData['type'];
}
$join[] = $this->buildJoinStatement(array( $join[] = $this->buildJoinStatement(array(
'table' => $this->fullTableName($model->{$assoc}), 'table' => $this->fullTableName($model->{$assoc}),
'alias' => $assoc, 'alias' => $assoc,
'type' => $type, 'type' => isset($assocData['type']) ? $assocData['type'] : 'LEFT',
'conditions' => trim($this->conditions($this->getConstraint($assocData['association'], $model, $model->{$assoc}, $assoc, $assocData), true, false)) 'conditions' => trim($this->conditions($this->getConstraint($assocData['association'], $model, $model->{$assoc}, $assoc, $assocData), true, false))
)); ));
} }
} }
return $join; return $join;
} }
/**
* Returns the an SQL calculation, i.e. COUNT() or MAX()
*
* @param string $func Lowercase name of SQL function, i.e. 'count' or 'max'
* @param array $params Function parameters (any values must be quoted manually)
* @return string An SQL calculation function
* @access public
*/
function calculate($func, $params = array()) {
switch (strtolower($func)) {
case 'count':
if (!isset($params[0])) {
$params[0] = '*';
}
if (!isset($params[1])) {
$params[1] = 'count';
}
return 'COUNT(' . $this->name($params[0]) . ') AS ' . $this->name($params[1]);
case 'max':
if (!isset($params[1])) {
$params[1] = $params[0];
}
return 'MAX(' . $this->name($params[0]) . ') AS ' . $this->name($params[1]);
}
}
/** /**
* Deletes all the records in a table and resets the count of the auto-incrementing * Deletes all the records in a table and resets the count of the auto-incrementing
* primary key, where applicable. * primary key, where applicable.
@ -1484,6 +1393,36 @@ class DboSource extends DataSource {
function truncate($table) { function truncate($table) {
return $this->execute('TRUNCATE TABLE ' . $this->fullTableName($table)); return $this->execute('TRUNCATE TABLE ' . $this->fullTableName($table));
} }
/**
* Commit a transaction
*
* @param model $model
* @return boolean True on success, false on fail
* (i.e. if the database/model does not support transactions,
* or a transaction has not started).
*/
function commit(&$model) {
if (parent::commit($model) && $this->execute('COMMIT')) {
$this->_transactionStarted = false;
return true;
}
return false;
}
/**
* Rollback a transaction
*
* @param model $model
* @return boolean True on success, false on fail
* (i.e. if the database/model does not support transactions,
* or a transaction has not started).
*/
function rollback(&$model) {
if (parent::rollback($model) && $this->execute('ROLLBACK')) {
$this->_transactionStarted = false;
return true;
}
return false;
}
/** /**
* Creates a default set of conditions from the model if $conditions is null/empty. * Creates a default set of conditions from the model if $conditions is null/empty.
* *
@ -1523,26 +1462,19 @@ class DboSource extends DataSource {
} }
return $key; return $key;
} }
/**
* Returns the column type of a given
*
* @param Model $model
* @param string $field
*/
function getColumnType(&$model, $field) {
return $model->getColumnType($field);
}
/** /**
* Private helper method to remove query metadata in given data array. * Private helper method to remove query metadata in given data array.
* *
* @param array $data * @param array $data
* @return array
*/ */
function __scrubQueryData(&$data) { function __scrubQueryData($data) {
foreach (array('conditions', 'fields', 'joins', 'order', 'limit', 'offset') as $key) { foreach (array('conditions', 'fields', 'joins', 'order', 'limit', 'offset') as $key) {
if (!isset($data[$key]) || empty($data[$key])) { if (!isset($data[$key]) || empty($data[$key])) {
$data[$key] = array(); $data[$key] = array();
} }
} }
return $data;
} }
/** /**
* Generates the fields list of an SQL query. * Generates the fields list of an SQL query.
@ -1782,14 +1714,12 @@ class DboSource extends DataSource {
* @access private * @access private
*/ */
function __quoteFields($conditions) { function __quoteFields($conditions) {
$start = null; $start = $end = null;
$end = null;
$original = $conditions; $original = $conditions;
if (!empty($this->startQuote)) { if (!empty($this->startQuote)) {
$start = preg_quote($this->startQuote); $start = preg_quote($this->startQuote);
} }
if (!empty($this->endQuote)) { if (!empty($this->endQuote)) {
$end = preg_quote($this->endQuote); $end = preg_quote($this->endQuote);
} }
@ -1840,8 +1770,7 @@ class DboSource extends DataSource {
*/ */
function order($keys, $direction = 'ASC') { function order($keys, $direction = 'ASC') {
if (is_string($keys) && strpos($keys, ',') && !preg_match('/\(.+\,.+\)/', $keys)) { if (is_string($keys) && strpos($keys, ',') && !preg_match('/\(.+\,.+\)/', $keys)) {
$keys = explode(',', $keys); $keys = array_map('trim', explode(',', $keys));
array_map('trim', $keys);
} }
if (is_array($keys)) { if (is_array($keys)) {
@ -1949,9 +1878,8 @@ class DboSource extends DataSource {
if (is_array($out)) { if (is_array($out)) {
return $out[0]['count']; return $out[0]['count'];
} else {
return false;
} }
return false;
} }
/** /**
* Gets the length of a database-native column description, or null if no length * Gets the length of a database-native column description, or null if no length
@ -1966,7 +1894,6 @@ class DboSource extends DataSource {
if (strpos($col, '(') !== false) { if (strpos($col, '(') !== false) {
list($col, $limit) = explode('(', $col); list($col, $limit) = explode('(', $col);
} }
if ($limit != null) { if ($limit != null) {
return intval($limit); return intval($limit);
} }
@ -1984,25 +1911,10 @@ class DboSource extends DataSource {
return 1; return 1;
} }
return 0; return 0;
} else { } else {
if (!empty($data)) { return !empty($data);
return true;
}
return false;
} }
} }
/**
* Destructor. Closes connection to the database.
*
*/
function __destruct() {
if ($this->_transactionStarted) {
$null = null;
$this->rollback($null);
}
parent::__destruct();
}
/** /**
* Inserts multiple values into a join table * Inserts multiple values into a join table
* *

View file

@ -1549,21 +1549,15 @@ class Model extends Overloadable {
$db =& ConnectionManager::getDataSource($this->useDbConfig); $db =& ConnectionManager::getDataSource($this->useDbConfig);
foreach ($this->hasAndBelongsToMany as $assoc => $data) { foreach ($this->hasAndBelongsToMany as $assoc => $data) {
if (isset($data['with'])) { $records = $this->{$data['with']}->find('all', array(
$records = $this->{$data['with']}->find('all', array( 'conditions' => array($data['foreignKey'] => $id),
'conditions' => array($data['foreignKey'] => $id), 'fields' => $this->{$data['with']}->primaryKey,
'fields' => $this->{$data['with']}->primaryKey, 'recursive' => -1
'recursive' => -1 ));
)); if (!empty($records)) {
if (!empty($records)) { foreach ($records as $record) {
foreach ($records as $record) { $this->{$data['with']}->delete($record[$this->{$data['with']}->alias][$this->{$data['with']}->primaryKey]);
$this->{$data['with']}->delete($record[$this->{$data['with']}->alias][$this->{$data['with']}->primaryKey]);
}
} }
} else {
$table = $db->name($db->fullTableName($data['joinTable']));
$conditions = $db->name($data['foreignKey']) . ' = ' . $db->value($id);
$db->query("DELETE FROM {$table} WHERE {$conditions}");
} }
} }
} }
@ -1785,7 +1779,7 @@ class Model extends Overloadable {
if ($state == 'before') { if ($state == 'before') {
if (empty($query['fields'])) { if (empty($query['fields'])) {
$db =& ConnectionManager::getDataSource($this->useDbConfig); $db =& ConnectionManager::getDataSource($this->useDbConfig);
$query['fields'] = 'COUNT(*) AS ' . $db->name('count'); $query['fields'] = $db->calculate('count');
} }
$query['order'] = false; $query['order'] = false;
return $query; return $query;

View file

@ -114,16 +114,27 @@ class DboPostgresTest extends CakeTestCase {
* @access public * @access public
*/ */
function skip() { function skip() {
$this->_initDb();
$db = ConnectionManager::getDataSource('test_suite'); $db = ConnectionManager::getDataSource('test_suite');
$this->skipif ($this->db->config['driver'] != 'postgres', 'PostgreSQL connection not available'); $this->skipif ($this->db->config['driver'] != 'postgres', 'PostgreSQL connection not available');
} }
/**
* Set up test suite database connection
*
* @access public
*/
function startTest() {
$this->_initDb();
}
/** /**
* Sets up a Dbo class instance for testing * Sets up a Dbo class instance for testing
* *
* @access public * @access public
*/ */
function setUp() { function setUp() {
$this->startTest();
$db = ConnectionManager::getDataSource('test_suite'); $db = ConnectionManager::getDataSource('test_suite');
$this->db = new DboPostgresTestDb($db->config); $this->db = new DboPostgresTestDb($db->config);
$this->model = new PostgresTestModel(); $this->model = new PostgresTestModel();
@ -173,6 +184,11 @@ class DboPostgresTest extends CakeTestCase {
$result = $this->db->value('1,2', 'float'); $result = $this->db->value('1,2', 'float');
$this->assertIdentical($expected, $result); $this->assertIdentical($expected, $result);
} }
function testColumnParsing() {
var_export($this->db->isConnected());
var_export($this->db->fetchAll("SELECT table_name as name FROM INFORMATION_SCHEMA.tables;"));
}
} }
?> ?>

View file

@ -247,7 +247,7 @@ class TestModel8 extends CakeTestModel {
var $hasOne = array( var $hasOne = array(
'TestModel9' => array( 'TestModel9' => array(
'className' => 'TestModel9', 'className' => 'TestModel9',
'foreignKey' => 'test_model9_id', 'foreignKey' => 'test_model8_id',
'conditions' => 'TestModel9.name != \'mariano\'' 'conditions' => 'TestModel9.name != \'mariano\''
) )
); );
@ -678,7 +678,7 @@ class DboSourceTest extends CakeTestCase {
$external = isset($assocData['external']); $external = isset($assocData['external']);
if ($this->Model->Category2->alias == $linkModel->alias && $type != 'hasAndBelongsToMany' && $type != 'hasMany') { if ($this->Model->Category2->alias == $linkModel->alias && $type != 'hasAndBelongsToMany' && $type != 'hasMany') {
$result = $this->db->generateSelfAssociationQuery($this->Model->Category2, $linkModel, $type, $assoc, $assocData, $queryData, $external, $null); $result = $this->db->generateAssociationQuery($this->Model->Category2, $linkModel, $type, $assoc, $assocData, $queryData, $external, $null);
$this->assertTrue($result); $this->assertTrue($result);
} else { } else {
if ($this->Model->Category2->useDbConfig == $linkModel->useDbConfig) { if ($this->Model->Category2->useDbConfig == $linkModel->useDbConfig) {
@ -690,7 +690,7 @@ class DboSourceTest extends CakeTestCase {
} }
$query = $this->db->generateAssociationQuery($this->Model->Category2, $null, null, null, null, $queryData, false, $null); $query = $this->db->generateAssociationQuery($this->Model->Category2, $null, null, null, null, $queryData, false, $null);
$this->assertPattern('/^SELECT\s+(.+)FROM(.+)`Category2`\.`group_id`\s+=\s+`Group`\.`id`\)\s+WHERE/', $query); $this->assertPattern('/^SELECT\s+(.+)FROM(.+)`Category2`\.`group_id`\s+=\s+`Group`\.`id`\)\s+LEFT JOIN(.+)WHERE\s+1 = 1\s*$/', $query);
$this->Model = new TestModel4(); $this->Model = new TestModel4();
$this->Model->schema(); $this->Model->schema();
@ -703,10 +703,11 @@ class DboSourceTest extends CakeTestCase {
$params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding);
$result = $this->db->generateSelfAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external'], $resultSet); $_queryData = $queryData;
$result = $this->db->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external'], $resultSet);
$this->assertTrue($result); $this->assertTrue($result);
$expected = array(array( $expected = array(
'fields' => array( 'fields' => array(
'`TestModel4`.`id`', '`TestModel4`.`id`',
'`TestModel4`.`name`', '`TestModel4`.`name`',
@ -722,18 +723,15 @@ class DboSourceTest extends CakeTestCase {
'table' => '`test_model4`', 'table' => '`test_model4`',
'alias' => 'TestModel4Parent', 'alias' => 'TestModel4Parent',
'type' => 'LEFT', 'type' => 'LEFT',
'conditions' => array('`TestModel4`.`parent_id`' => '{$__cakeIdentifier[TestModel4Parent.id]__$}') 'conditions' => '`TestModel4`.`parent_id` = `TestModel4Parent`.`id`'
) )
), ),
'table' => '`test_model4`',
'alias' => 'TestModel4',
'limit' => array(), 'limit' => array(),
'offset' => array(), 'offset' => array(),
'conditions' => array(), 'conditions' => array(),
'order' => array() 'order' => array()
)); );
$this->assertEqual($queryData, $expected);
$this->assertEqual($queryData['selfJoin'], $expected);
$result = $this->db->generateAssociationQuery($this->Model, $null, null, null, null, $queryData, false, $null); $result = $this->db->generateAssociationQuery($this->Model, $null, null, null, null, $queryData, false, $null);
$this->assertPattern('/^SELECT\s+`TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`, `TestModel4Parent`\.`id`, `TestModel4Parent`\.`name`, `TestModel4Parent`\.`created`, `TestModel4Parent`\.`updated`\s+/', $result); $this->assertPattern('/^SELECT\s+`TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`, `TestModel4Parent`\.`id`, `TestModel4Parent`\.`name`, `TestModel4Parent`\.`created`, `TestModel4Parent`\.`updated`\s+/', $result);
@ -743,9 +741,9 @@ class DboSourceTest extends CakeTestCase {
$params['assocData']['type'] = 'INNER'; $params['assocData']['type'] = 'INNER';
$this->Model->belongsTo['TestModel4Parent']['type'] = 'INNER'; $this->Model->belongsTo['TestModel4Parent']['type'] = 'INNER';
$result = $this->db->generateSelfAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external'], $resultSet); $result = $this->db->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $_queryData, $params['external'], $resultSet);
$this->assertTrue($result); $this->assertTrue($result);
$this->assertEqual($queryData['joins'][0]['type'], 'INNER'); $this->assertEqual($_queryData['joins'][0]['type'], 'INNER');
} }
function testGenerateInnerJoinAssociationQuery() { function testGenerateInnerJoinAssociationQuery() {
@ -777,16 +775,14 @@ class DboSourceTest extends CakeTestCase {
$null = null; $null = null;
$params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding);
$_queryData = $queryData;
$result = $this->db->generateSelfAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external'], $resultSet); $result = $this->db->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external'], $resultSet);
$this->assertTrue($result); $this->assertTrue($result);
$result = $this->db->generateAssociationQuery($this->Model, $null, null, null, null, $queryData, false, $null); $result = $this->db->generateAssociationQuery($this->Model, $null, null, null, null, $queryData, false, $null);
$this->assertPattern('/^SELECT\s+`TestModel8`\.`id`, `TestModel8`\.`test_model9_id`, `TestModel8`\.`name`, `TestModel8`\.`created`, `TestModel8`\.`updated`, `TestModel9`\.`id`, `TestModel9`\.`test_model8_id`, `TestModel9`\.`name`, `TestModel9`\.`created`, `TestModel9`\.`updated`\s+/', $result); $this->assertPattern('/^SELECT\s+`TestModel8`\.`id`, `TestModel8`\.`test_model9_id`, `TestModel8`\.`name`, `TestModel8`\.`created`, `TestModel8`\.`updated`, `TestModel9`\.`id`, `TestModel9`\.`test_model8_id`, `TestModel9`\.`name`, `TestModel9`\.`created`, `TestModel9`\.`updated`\s+/', $result);
$this->assertPattern('/FROM\s+`test_model8` AS `TestModel8`\s+LEFT JOIN\s+`test_model9` AS `TestModel9`/', $result); $this->assertPattern('/FROM\s+`test_model8` AS `TestModel8`\s+LEFT JOIN\s+`test_model9` AS `TestModel9`/', $result);
$this->assertPattern('/\s+ON\s+\(`TestModel8`.`test_model9_id` = `TestModel9`.`id`\s+AND\s+`TestModel9`\.`name` != \'mariano\'\)\s+WHERE/', $result); $this->assertPattern('/\s+ON\s+\(`TestModel9`\.`name` != \'mariano\'\s+AND\s+`TestModel9`.`test_model8_id` = `TestModel8`.`id`\)\s+WHERE/', $result);
$this->assertPattern('/\s+WHERE\s+(?:\()?1\s+=\s+1(?:\))?\s*$/', $result); $this->assertPattern('/\s+WHERE\s+(?:\()?1\s+=\s+1(?:\))?\s*$/', $result);
} }
@ -801,16 +797,13 @@ class DboSourceTest extends CakeTestCase {
$null = null; $null = null;
$params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding);
$result = $this->db->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external'], $resultSet);
$result = $this->db->generateSelfAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external'], $resultSet);
$this->assertTrue($result); $this->assertTrue($result);
$result = $this->db->generateAssociationQuery($this->Model, $null, null, null, null, $queryData, false, $null); $result = $this->db->generateAssociationQuery($this->Model, $null, null, null, null, $queryData, false, $null);
$this->assertPattern('/^SELECT\s+`TestModel9`\.`id`, `TestModel9`\.`test_model8_id`, `TestModel9`\.`name`, `TestModel9`\.`created`, `TestModel9`\.`updated`, `TestModel8`\.`id`, `TestModel8`\.`test_model9_id`, `TestModel8`\.`name`, `TestModel8`\.`created`, `TestModel8`\.`updated`\s+/', $result); $this->assertPattern('/^SELECT\s+`TestModel9`\.`id`, `TestModel9`\.`test_model8_id`, `TestModel9`\.`name`, `TestModel9`\.`created`, `TestModel9`\.`updated`, `TestModel8`\.`id`, `TestModel8`\.`test_model9_id`, `TestModel8`\.`name`, `TestModel8`\.`created`, `TestModel8`\.`updated`\s+/', $result);
$this->assertPattern('/FROM\s+`test_model9` AS `TestModel9`\s+LEFT JOIN\s+`test_model8` AS `TestModel8`/', $result); $this->assertPattern('/FROM\s+`test_model9` AS `TestModel9`\s+LEFT JOIN\s+`test_model8` AS `TestModel8`/', $result);
$this->assertPattern('/\s+ON\s+\(`TestModel9`.`test_model8_id` = `TestModel8`.`id`\s+AND\s+`TestModel8`\.`name` != \'larry\'\)\s+WHERE/', $result); $this->assertPattern('/\s+ON\s+\(`TestModel8`\.`name` != \'larry\'\s+AND\s+`TestModel9`.`test_model8_id` = `TestModel8`.`id`\)\s+WHERE/', $result);
$this->assertPattern('/\s+WHERE\s+(?:\()?1\s+=\s+1(?:\))?\s*$/', $result); $this->assertPattern('/\s+WHERE\s+(?:\()?1\s+=\s+1(?:\))?\s*$/', $result);
} }
@ -826,8 +819,7 @@ class DboSourceTest extends CakeTestCase {
$params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding);
$result = $this->db->generateSelfAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external'], $resultSet); $result = $this->db->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external'], $resultSet);
$this->assertTrue($result); $this->assertTrue($result);
$result = $this->db->generateAssociationQuery($this->Model, $null, null, null, null, $queryData, false, $null); $result = $this->db->generateAssociationQuery($this->Model, $null, null, null, null, $queryData, false, $null);
@ -857,8 +849,7 @@ class DboSourceTest extends CakeTestCase {
$params = &$this->_prepareAssociationQuery($this->Featured2, $queryData, $binding); $params = &$this->_prepareAssociationQuery($this->Featured2, $queryData, $binding);
$result = $this->db->generateSelfAssociationQuery($this->Featured2, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external'], $resultSet); $result = $this->db->generateAssociationQuery($this->Featured2, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external'], $resultSet);
$this->assertTrue($result); $this->assertTrue($result);
$result = $this->db->generateAssociationQuery($this->Featured2, $null, null, null, null, $queryData, false, $null); $result = $this->db->generateAssociationQuery($this->Featured2, $null, null, null, null, $queryData, false, $null);
@ -867,9 +858,10 @@ class DboSourceTest extends CakeTestCase {
'/^SELECT\s+`Featured2`\.`id`, `Featured2`\.`article_id`, `Featured2`\.`category_id`, `Featured2`\.`name`,\s+'. '/^SELECT\s+`Featured2`\.`id`, `Featured2`\.`article_id`, `Featured2`\.`category_id`, `Featured2`\.`name`,\s+'.
'`ArticleFeatured2`\.`id`, `ArticleFeatured2`\.`title`, `ArticleFeatured2`\.`user_id`, `ArticleFeatured2`\.`published`\s+' . '`ArticleFeatured2`\.`id`, `ArticleFeatured2`\.`title`, `ArticleFeatured2`\.`user_id`, `ArticleFeatured2`\.`published`\s+' .
'FROM\s+`featured2` AS `Featured2`\s+LEFT JOIN\s+`article_featured` AS `ArticleFeatured2`' . 'FROM\s+`featured2` AS `Featured2`\s+LEFT JOIN\s+`article_featured` AS `ArticleFeatured2`' .
'\s+ON\s+\(`Featured2`\.`article_featured2_id` = `ArticleFeatured2`\.`id`\s+AND\s+`ArticleFeatured2`.`published` = \'Y\'\)' . '\s+ON\s+\(`ArticleFeatured2`.`published` = \'Y\'\s+AND\s+`Featured2`\.`article_featured2_id` = `ArticleFeatured2`\.`id`\)' .
'\s+WHERE\s+1\s+=\s+1\s*$/', '\s+WHERE\s+1\s+=\s+1\s*$/',
$result); $result
);
} }
function testGenerateAssociationQueryHasOne() { function testGenerateAssociationQueryHasOne() {
@ -1367,16 +1359,9 @@ class DboSourceTest extends CakeTestCase {
$linkModel =& $model->{$className}; $linkModel =& $model->{$className};
$external = isset($assocData['external']); $external = isset($assocData['external']);
$queryData = $this->db->__scrubQueryData($queryData);
$this->db->__scrubQueryData($queryData); $result = array_merge(array('linkModel' => &$linkModel), compact('type', 'assoc', 'assocData', 'external'));
$result = array(
'linkModel'=> &$linkModel,
'type'=> $type,
'assoc'=> $assoc,
'assocData'=> $assocData,
'external'=> $external
);
return $result; return $result;
} }
@ -2152,6 +2137,29 @@ class DboSourceTest extends CakeTestCase {
$result = $this->db->order("Model.name+0 ASC"); $result = $this->db->order("Model.name+0 ASC");
$this->assertPattern("/^\s*ORDER BY\s+`Model`\.`name`\+0\s+ASC\s*$/", $result); $this->assertPattern("/^\s*ORDER BY\s+`Model`\.`name`\+0\s+ASC\s*$/", $result);
} }
function testCalculations() {
$result = $this->db->calculate('count');
$this->assertEqual($result, 'COUNT(*) AS `count`');
$result = $this->db->calculate('count', array('id'));
$this->assertEqual($result, 'COUNT(`id`) AS `count`');
$result = $this->db->calculate('count', array('id', 'id_count'));
$this->assertEqual($result, 'COUNT(`id`) AS `id_count`');
$result = $this->db->calculate('count', array('Model.id', 'id_count'));
$this->assertEqual($result, 'COUNT(`Model`.`id`) AS `id_count`');
$result = $this->db->calculate('max', array('id'));
$this->assertEqual($result, 'MAX(`id`) AS `id`');
$result = $this->db->calculate('max', array('Model.id', 'id'));
$this->assertEqual($result, 'MAX(`Model`.`id`) AS `id`');
$result = $this->db->calculate('max', array('`Model`.`id`', 'id'));
$this->assertEqual($result, 'MAX(`Model`.`id`) AS `id`');
}
} }
?> ?>

View file

@ -83,6 +83,7 @@ class ModelTest extends CakeTestCase {
$this->DeviceType->recursive = 2; $this->DeviceType->recursive = 2;
$result = $this->DeviceType->read(null, 1); $result = $this->DeviceType->read(null, 1);
$expected = array( $expected = array(
'DeviceType' => array( 'DeviceType' => array(
'id' => 1, 'device_type_category_id' => 1, 'feature_set_id' => 1, 'exterior_type_category_id' => 1, 'image_id' => 1, 'id' => 1, 'device_type_category_id' => 1, 'feature_set_id' => 1, 'exterior_type_category_id' => 1, 'image_id' => 1,
@ -143,12 +144,33 @@ class ModelTest extends CakeTestCase {
$this->assertEqual($result['Tag'], $expected); $this->assertEqual($result['Tag'], $expected);
} }
function testHasManyOptimization() { function testHabtmLimitOptimization() {
$this->loadFixtures('Article', 'User', 'Comment', 'Tag', 'ArticlesTag');
$this->model =& new Article();
$this->model->hasAndBelongsToMany['Tag']['limit'] = 1;
$result = $this->model->read(null, 2);
$expected = array(
'Article' => array('id' => '2', 'user_id' => '3', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31'),
'User' => array('id' => '3', 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31'),
'Comment' => array(
array('id' => '5', 'article_id' => '2', 'user_id' => '1', 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31'),
array('id' => '6', 'article_id' => '2', 'user_id' => '2', 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31')
),
'Tag' => array(
array('id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31'),
array('id' => '3', 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31')
)
);
//$this->assertEqual($result, $expected);
}
function testHasManyLimitOptimization() {
$this->loadFixtures('Project', 'Thread', 'Message', 'Bid'); $this->loadFixtures('Project', 'Thread', 'Message', 'Bid');
$this->Project =& new Project(); $this->Project =& new Project();
$this->Project->recursive = 3; $this->Project->recursive = 3;
$result = $this->Project->findAll(); $result = $this->Project->find('all');
$expected = array( $expected = array(
array('Project' => array('id' => 1, 'name' => 'Project 1'), array('Project' => array('id' => 1, 'name' => 'Project 1'),
'Thread' => array(array('id' => 1, 'project_id' => 1, 'name' => 'Project 1, Thread 1', 'Thread' => array(array('id' => 1, 'project_id' => 1, 'name' => 'Project 1, Thread 1',
@ -1702,14 +1724,11 @@ class ModelTest extends CakeTestCase {
'Tag' => array('Tag' => array(1, 2)) 'Tag' => array('Tag' => array(1, 2))
); );
$result = $this->model->set($data); $this->assertTrue($this->model->set($data));
$this->assertTrue($result); $this->assertTrue($this->model->save());
$result = $this->model->save();
$this->assertTrue($result);
$this->model->unbindModel(array('belongsTo' => array('User'), 'hasMany' => array('Comment'))); $this->model->unbindModel(array('belongsTo' => array('User'), 'hasMany' => array('Comment')));
$result = $this->model->find(array('Article.id'=>2), array('id', 'user_id', 'title', 'body')); $result = $this->model->find(array('Article.id' => 2), array('id', 'user_id', 'title', 'body'));
$expected = array( $expected = array(
'Article' => array('id' => '2', 'user_id' => '3', 'title' => 'New Second Article', 'body' => 'Second Article Body'), 'Article' => array('id' => '2', 'user_id' => '3', 'title' => 'New Second Article', 'body' => 'Second Article Body'),
'Tag' => array( 'Tag' => array(
@ -1981,13 +2000,16 @@ class ModelTest extends CakeTestCase {
$this->model =& new Article(); $this->model =& new Article();
$this->model->belongsTo = $this->model->hasAndBelongsToMany = array(); $this->model->belongsTo = $this->model->hasAndBelongsToMany = array();
$this->assertTrue($this->model->saveAll(array( $this->assertTrue($this->model->saveAll(
'Article' => array('id' => 2), array(
'Comment' => array( 'Article' => array('id' => 2),
array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1), 'Comment' => array(
array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2) array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1),
) array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2)
))); )
),
array('atomic' => false)
));
$result = $this->model->findById(2); $result = $this->model->findById(2);
$expected = array('First Comment for Second Article', 'Second Comment for Second Article', 'First new comment', 'Second new comment'); $expected = array('First Comment for Second Article', 'Second Comment for Second Article', 'First new comment', 'Second new comment');
$this->assertEqual(Set::extract($result['Comment'], '{n}.comment'), $expected); $this->assertEqual(Set::extract($result['Comment'], '{n}.comment'), $expected);
@ -2000,7 +2022,7 @@ class ModelTest extends CakeTestCase {
$data = array( $data = array(
array('id' => '1', 'title' => 'Baleeted First Post', 'body' => 'Baleeted!', 'published' => 'N'), array('id' => '1', 'title' => 'Baleeted First Post', 'body' => 'Baleeted!', 'published' => 'N'),
array('id' => '2', 'title' => 'Just update the title'), array('id' => '2', 'title' => 'Just update the title'),
array('title' => 'Creating a fourth post', 'body' => 'Fourth post body') array('title' => 'Creating a fourth post', 'body' => 'Fourth post body', 'author_id' => 2)
); );
$ts = date('Y-m-d H:i:s'); $ts = date('Y-m-d H:i:s');
$this->assertTrue($this->model->saveAll($data)); $this->assertTrue($this->model->saveAll($data));
@ -2010,7 +2032,7 @@ class ModelTest extends CakeTestCase {
array('Post' => array('id' => '1', 'author_id' => '1', 'title' => 'Baleeted First Post', 'body' => 'Baleeted!', 'published' => 'N', 'created' => '2007-03-18 10:39:23', 'updated' => $ts)), array('Post' => array('id' => '1', 'author_id' => '1', 'title' => 'Baleeted First Post', 'body' => 'Baleeted!', 'published' => 'N', 'created' => '2007-03-18 10:39:23', 'updated' => $ts)),
array('Post' => array('id' => '2', 'author_id' => '3', 'title' => 'Just update the title', 'body' => 'Second Post Body', 'published' => 'N', 'created' => '2007-03-18 10:41:23', 'updated' => $ts)), array('Post' => array('id' => '2', 'author_id' => '3', 'title' => 'Just update the title', 'body' => 'Second Post Body', 'published' => 'N', 'created' => '2007-03-18 10:41:23', 'updated' => $ts)),
array('Post' => array('id' => '3', 'author_id' => '1', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31')), array('Post' => array('id' => '3', 'author_id' => '1', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31')),
array('Post' => array('id' => '4', 'author_id' => '0', 'title' => 'Creating a fourth post', 'body' => 'Fourth post body', 'published' => 'N', 'created' => $ts, 'updated' => $ts)) array('Post' => array('id' => '4', 'author_id' => '2', 'title' => 'Creating a fourth post', 'body' => 'Fourth post body', 'published' => 'N', 'created' => $ts, 'updated' => $ts))
); );
$this->assertEqual($result, $expected); $this->assertEqual($result, $expected);
@ -2077,17 +2099,17 @@ class ModelTest extends CakeTestCase {
$this->model =& new Syfile(); $this->model =& new Syfile();
$this->model2 =& new Item(); $this->model2 =& new Item();
$this->model2->belongsTo['Syfile']['counterCache'] = true; $this->model2->belongsTo['Syfile']['counterCache'] = true;
$this->model2->belongsTo['Syfile']['counterScope'] = 'published = 1'; $this->model2->belongsTo['Syfile']['counterScope'] = array('published' => true);
$result = $this->model->findById(1); $result = $this->model->findById(1);
$this->assertIdentical($result['Syfile']['item_count'], null); $this->assertIdentical($result['Syfile']['item_count'], null);
$this->model2->save(array('name' => 'Item 7', 'syfile_id' => 1, 'published'=> 1)); $this->model2->save(array('name' => 'Item 7', 'syfile_id' => 1, 'published'=> true));
$result = $this->model->findById(1); $result = $this->model->findById(1);
$this->assertIdentical($result['Syfile']['item_count'], '1'); $this->assertIdentical($result['Syfile']['item_count'], '1');
$this->model2->id = 1; $this->model2->id = 1;
$this->model2->saveField('published', 1); $this->model2->saveField('published', true);
$result = $this->model->findById(1); $result = $this->model->findById(1);
$this->assertIdentical($result['Syfile']['item_count'], '2'); $this->assertIdentical($result['Syfile']['item_count'], '2');
} }
@ -2220,6 +2242,29 @@ class ModelTest extends CakeTestCase {
$this->assertEqual($this->model->Comment->find('count'), 2); $this->assertEqual($this->model->Comment->find('count'), 2);
} }
function testDeleteLinks() {
$this->loadFixtures('Article', 'ArticlesTag', 'Tag');
$this->model =& new Article();
$result = $this->model->ArticlesTag->find('all');
$expected = array(
array('ArticlesTag' => array('article_id' => '1', 'tag_id' => '1')),
array('ArticlesTag' => array('article_id' => '1', 'tag_id' => '2')),
array('ArticlesTag' => array('article_id' => '2', 'tag_id' => '1')),
array('ArticlesTag' => array('article_id' => '2', 'tag_id' => '3'))
);
$this->assertEqual($result, $expected);
$this->Article->delete(1);
$result = $this->model->ArticlesTag->find('all');
$expected = array(
array('ArticlesTag' => array('article_id' => '2', 'tag_id' => '1')),
array('ArticlesTag' => array('article_id' => '2', 'tag_id' => '3'))
);
$this->assertEqual($result, $expected);
}
function testFindAllThreaded() { function testFindAllThreaded() {
$this->loadFixtures('Category'); $this->loadFixtures('Category');
$this->model =& new Category(); $this->model =& new Category();

View file

@ -130,7 +130,7 @@ class ArticleFeatured extends CakeTestModel {
var $name = 'ArticleFeatured'; var $name = 'ArticleFeatured';
var $belongsTo = array('User', 'Category'); var $belongsTo = array('User', 'Category');
var $hasOne = array('Featured'); var $hasOne = array('Featured');
var $hasMany = array('Comment' => array('className'=>'Comment', 'dependent' => true)); var $hasMany = array('Comment' => array('className' => 'Comment', 'dependent' => true));
var $hasAndBelongsToMany = array('Tag'); var $hasAndBelongsToMany = array('Tag');
var $validate = array('user_id' => VALID_NUMBER, 'title' => VALID_NOT_EMPTY, 'body' => VALID_NOT_EMPTY); var $validate = array('user_id' => VALID_NUMBER, 'title' => VALID_NOT_EMPTY, 'body' => VALID_NOT_EMPTY);
} }
@ -142,10 +142,7 @@ class ArticleFeatured extends CakeTestModel {
*/ */
class Featured extends CakeTestModel { class Featured extends CakeTestModel {
var $name = 'Featured'; var $name = 'Featured';
var $belongsTo = array( var $belongsTo = array('ArticleFeatured', 'Category');
'ArticleFeatured'=> array('className' => 'ArticleFeatured'),
'Category'=> array('className' => 'Category')
);
} }
/** /**
@ -354,7 +351,7 @@ class NodeNoAfterFind extends CakeTestModel {
var $validate = array('name' => VALID_NOT_EMPTY); var $validate = array('name' => VALID_NOT_EMPTY);
var $useTable = 'apples'; var $useTable = 'apples';
var $hasOne = array('Sample' => array('className' => 'NodeAfterFindSample')); var $hasOne = array('Sample' => array('className' => 'NodeAfterFindSample'));
var $hasMany = array('Child' => array( 'className' => 'NodeAfterFind', 'dependent' => true)); var $hasMany = array('Child' => array('className' => 'NodeAfterFind', 'dependent' => true));
var $belongsTo = array('Parent' => array('className' => 'NodeAfterFind', 'foreignKey' => 'apple_id')); var $belongsTo = array('Parent' => array('className' => 'NodeAfterFind', 'foreignKey' => 'apple_id'));
} }
class ModelA extends CakeTestModel { class ModelA extends CakeTestModel {
@ -455,6 +452,11 @@ class JoinC extends CakeTestModel {
var $name = 'JoinC'; var $name = 'JoinC';
var $hasAndBelongsToMany = array('JoinA'); var $hasAndBelongsToMany = array('JoinA');
} }
class ThePaper extends CakeTestModel {
var $name = 'ThePaper';
var $useTable = 'apples';
var $hasOne = array('Itself' => array('className' => 'ThePaper', 'foreignKey' => 'apple_id'));
}
/** /**
* Short description for class. * Short description for class.
* *