From 5197bf60d361b29c6ab192aad706188fc21bdcf4 Mon Sep 17 00:00:00 2001 From: nate Date: Tue, 20 Mar 2007 17:38:53 +0000 Subject: [PATCH] Updating DboSource with new query generator, and updating model/dbo test cases git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@4636 3807eeeb-6ff5-0310-8944-8be069107fe0 --- cake/libs/model/datasources/dbo/dbo_mysql.php | 21 - .../model/datasources/dbo/dbo_postgres.php | 43 +- cake/libs/model/datasources/dbo_source.php | 632 ++++++++------- .../model/datasources/dbo_source.test.php | 738 ++++++++++-------- cake/tests/cases/libs/model/model.test.php | 14 +- cake/tests/groups/no_database.group.php | 1 - 6 files changed, 764 insertions(+), 685 deletions(-) diff --git a/cake/libs/model/datasources/dbo/dbo_mysql.php b/cake/libs/model/datasources/dbo/dbo_mysql.php index 168129031..1938bf9f3 100644 --- a/cake/libs/model/datasources/dbo/dbo_mysql.php +++ b/cake/libs/model/datasources/dbo/dbo_mysql.php @@ -203,27 +203,6 @@ class DboMysql extends DboSource { $this->__cacheDescription($this->fullTableName($model, false), $fields); return $fields; } -/** - * Returns a quoted name of $data for use in an SQL statement. - * - * @param string $data Name (table.field) to be prepared for use in an SQL statement - * @return string Quoted for MySQL - */ - function name($data) { - $tmp = parent::name($data); - if (!empty($tmp)) { - return $tmp; - } - - if ($data == '*') { - return '*'; - } - $pos = strpos($data, '`'); - if ($pos === false) { - $data = '`'. str_replace('.', '`.`', $data) .'`'; - } - return $data; - } /** * Returns a quoted and escaped string of $data for use in an SQL statement. * diff --git a/cake/libs/model/datasources/dbo/dbo_postgres.php b/cake/libs/model/datasources/dbo/dbo_postgres.php index bb25fb9cc..05f83b2c5 100644 --- a/cake/libs/model/datasources/dbo/dbo_postgres.php +++ b/cake/libs/model/datasources/dbo/dbo_postgres.php @@ -180,26 +180,6 @@ class DboPostgres extends DboSource { $this->__cacheDescription($model->tablePrefix . $model->table, $fields); return $fields; } - -/** - * Returns a quoted and escaped string of $data for use in an SQL statement. - * - * @param string $data String to be prepared for use in an SQL statement - * @return string Quoted and escaped - */ - function name($data) { - if ($data == '*') { - return '*'; - } - - $pos = strpos($data, '"'); - - if ($pos === false) { - $data = '"' . str_replace('.', '"."', $data) . '"'; - } - return $data; - } - /** * Returns a quoted and escaped string of $data for use in an SQL statement. * @@ -376,24 +356,15 @@ class DboPostgres extends DboSource { * @param mixed $fields * @return array */ - function fields(&$model, $alias, $fields) { - if (is_array($fields)) { - $fields = $fields; - } else { - if ($fields != null) { - if (strpos($fields, ',')) { - $fields = explode(',', $fields); - } else { - $fields = array($fields); - } - $fields = array_map('trim', $fields); - } else { - foreach($model->_tableInfo->value as $field) { - $fields[] = $field['name']; - } - } + function fields(&$model, $alias = null, $fields = array(), $quote = true) { + if (empty($alias)) { + $alias = $model->name; } + $fields = parent::fields($model, $alias, $fields, false); + if (!$quote) { + return $fields; + } $count = count($fields); if ($count >= 1 && $fields[0] != '*' && strpos($fields[0], 'COUNT(*)') === false) { diff --git a/cake/libs/model/datasources/dbo_source.php b/cake/libs/model/datasources/dbo_source.php index 9df27d648..bbca7d268 100644 --- a/cake/libs/model/datasources/dbo_source.php +++ b/cake/libs/model/datasources/dbo_source.php @@ -17,7 +17,7 @@ * * @filesource * @copyright Copyright 2005-2007, Cake Software Foundation, Inc. - * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project + * @link http://www.cakefoundation.org/projects/info/cakephp CakePHP Project * @package cake * @subpackage cake.cake.libs.model.datasources * @since CakePHP(tm) v 0.10.0.1076 @@ -369,13 +369,14 @@ class DboSource extends DataSource { function field($name, $sql) { $data = $this->fetchRow($sql); - if (empty($data[$name])) { + if (!isset($data[$name]) || empty($data[$name])) { return false; } else { return $data[$name]; } } /** + * Returns a quoted name of $data for use in an SQL statement. * Strips fields out of SQL functions before quoting. * * @param string $data @@ -388,7 +389,12 @@ class DboSource extends DataSource { return $fields[1] . '(' . $this->name($fields[2]) . ')'; } } - return null; + if ($data == '*') { + return '*'; + } + $data = $this->startQuote . str_replace('.', $this->endQuote . '.' . $this->startQuote, $data) . $this->endQuote; + $data = str_replace($this->startQuote . $this->startQuote, $this->startQuote, $data); + return str_replace($this->endQuote . $this->endQuote, $this->endQuote, $data); } /** * Checks if it's connected to the database @@ -571,6 +577,9 @@ class DboSource extends DataSource { if (!empty($queryData['fields'])) { $this->__bypass = true; + $queryData['fields'] = $this->fields($model, null, $queryData['fields']); + } else { + $queryData['fields'] = $this->fields($model); } foreach($model->__associations as $type) { @@ -818,7 +827,7 @@ class DboSource extends DataSource { $alias = $association; if (!isset($queryData['selfJoin'])) { $queryData['selfJoin'] = array(); - $sql = 'SELECT ' . join(', ', $this->fields($model, $model->name, $queryData['fields'])); + $sql = 'SELECT ' . join(', ', $this->fields($model, null, $queryData['fields'])); if($this->__bypass === false){ $sql .= ', '; $sql .= join(', ', $this->fields($linkModel, $alias, '')); @@ -868,6 +877,10 @@ class DboSource extends DataSource { $this->__scrubQueryData($assocData); $joinedOnSelf = false; + if (empty($queryData['fields'])) { + $queryData['fields'] = $this->fields($model, $model->name); + } + if ($linkModel == null) { if (array_key_exists('selfJoin', $queryData)) { return $this->generateSelfAssociationQuery($model, $linkModel, $type, $association, $assocData, $queryData, $external, $resultSet); @@ -878,21 +891,17 @@ class DboSource extends DataSource { } else { $joinFields = null; } - - $sql = 'SELECT '; - if ($this->goofyLimit) { - $sql .= $this->limit($queryData['limit'], $queryData['offset']); - } - $sql .= ' ' . join(', ', $this->fields($model, $model->name, $queryData['fields'])) . $joinFields . ' FROM '; - $sql .= $this->fullTableName($model) . ' ' . $this->alias; - $sql .= $this->name($model->name) . ' ' . join(' ', $queryData['joins']) . ' '; - $sql .= $this->conditions($queryData['conditions']) . ' ' . $this->order($queryData['order']); - - if (!$this->goofyLimit) { - $sql .= ' ' . $this->limit($queryData['limit'], $queryData['offset']); - } + return $this->buildStatement(array( + 'fields' => array_unique($queryData['fields']), + 'table' => $this->fullTableName($model), + 'alias' => $model->name, + 'limit' => $queryData['limit'], + 'offset' => $queryData['offset'], + 'joins' => $queryData['joins'], + 'conditions' => $queryData['conditions'], + 'order' => $queryData['order'] + ), $model); } - return $sql; } $alias = $association; @@ -901,18 +910,15 @@ class DboSource extends DataSource { } if ($external && isset($assocData['finderQuery'])) { - if (!empty($assocData['finderQuery']) && $assocData['finderQuery'] != null) { + if (!empty($assocData['finderQuery'])) { return $assocData['finderQuery']; } } - if (!$external && in_array($type, array('hasOne', 'belongsTo'))) { - if ($this->__bypass === false) { - $fields = join(', ', $this->fields($linkModel, $alias, $assocData['fields'])); - $this->__assocJoins['fields'][] = $fields; - } else { - $this->__assocJoins = null; - } + if ((!$external && in_array($type, array('hasOne', 'belongsTo')) && $this->__bypass === false) || $external) { + $fields = $this->fields($linkModel, $alias, $assocData['fields']); + } else { + $fields = array(); } $limit = ''; @@ -927,200 +933,172 @@ class DboSource extends DataSource { switch($type) { case 'hasOne': - if ($external) { - if (isset($queryData['limit']) && !empty($queryData['limit'])) { - $limit = $this->limit($queryData['limit'], $queryData['offset']); - } - - $sql = 'SELECT '; - if ($this->goofyLimit) { - $sql .= $limit; - } - - $sql .= ' ' . join(', ', $this->fields($linkModel, $alias, $assocData['fields'])); - $sql .= ' FROM ' . $this->fullTableName($linkModel) . ' ' . $this->alias . $this->name($alias) . ' '; - - $conditions = $queryData['conditions']; - $condition = $this->name($alias) . '.' . $this->name($assocData['foreignKey']); - $condition .= ' = {$__cakeForeignKey__$}'; - - if (is_array($conditions)) { - $conditions[] = $condition; - } else { - $cond = $this->name($alias) . '.' . $this->name($assocData['foreignKey']); - $cond .= ' = {$__cakeID__$}'; - - if (trim($conditions) != '') { - $conditions .= ' AND '; - } - $conditions .= $cond; - } - - $sql .= $this->conditions($conditions) . $this->order($queryData['order']); - if (!$this->goofyLimit) { - $sql .= $limit; - } - return $sql; - - } else { - - $sql = ' LEFT JOIN ' . $this->fullTableName($linkModel); - $sql .= ' ' . $this->alias . $this->name($alias) . ' ON '; - $sql .= $this->name($alias) . '.' . $this->name($assocData['foreignKey']); - $sql .= ' = ' . $model->escapeField($model->primaryKey); - - if ($assocData['order'] != null) { - $queryData['order'][] = $assocData['order']; - } - - $this->__mergeConditions($queryData, $assocData); - if (!in_array($sql, $queryData['joins'])) { - $queryData['joins'][] = $sql; - } - return true; - } - break; case 'belongsTo': if ($external) { - - $sql = 'SELECT '; - if ($this->goofyLimit) { - $sql .= $limit; + if ($type == 'hasOne') { + $conditions = $this->__mergeConditions($queryData['conditions'], array("{$alias}.{$assocData['foreignKey']}" => '{$__cakeForeignKey__$}')); + } elseif ($type == 'belongsTo') { + $conditions = $this->__mergeConditions($assocData['conditions'], array("{$alias}.{$linkModel->primaryKey}" => '{$__cakeForeignKey__$}')); } + $query = am($assocData, array( + 'conditions' => $conditions, + 'table' => $this->fullTableName($linkModel), + 'fields' => $fields, + 'alias' => $alias + )); - $sql .= ' ' . join(', ', $this->fields($linkModel, $alias, $assocData['fields'])); - $sql .= ' FROM ' . $this->fullTableName($linkModel) . ' ' . $this->alias . $this->name($alias) . ' '; - - $conditions = $assocData['conditions']; - $condition = $this->name($alias) . '.' . $this->name($linkModel->primaryKey); - $condition .= ' = {$__cakeForeignKey__$}'; - - if (is_array($conditions)) { - $conditions[] = $condition; - } else { - if (trim($conditions) != '') { - $conditions .= ' AND '; - } - $conditions .= $condition; + if ($type == 'belongsTo') { + // Dunno if we should be doing this for hasOne also...? + // Or maybe not doing it at all...? + $query = am($query, array( + 'order' => $assocData['order'], + 'limit' => $limit + )); } - - $sql .= $this->conditions($conditions) . $this->order($assocData['order']); - - if (!$this->goofyLimit) { - $sql .= $limit; - } - return $sql; - } else { + if ($type == 'hasOne') { + $conditions = array("{$alias}.{$assocData['foreignKey']}" => '{$__cakeIdentifier[' . "{$model->name}.{$model->primaryKey}" . ']__$}'); + } elseif ($type == 'belongsTo') { + $conditions = array($model->escapeField($assocData['foreignKey']) => '{$__cakeIdentifier[' . "{$alias}.{$linkModel->primaryKey}" . ']__$}'); + } - $sql = ' LEFT JOIN ' . $this->fullTableName($linkModel); - $sql .= ' ' . $this->alias . $this->name($alias) . ' ON '; - $sql .= $this->name($model->name) . '.' . $this->name($assocData['foreignKey']); - $sql .= ' = ' . $this->name($alias) . '.' . $this->name($linkModel->primaryKey); + $join = array( + 'table' => $this->fullTableName($linkModel), + 'alias' => $alias, + 'type' => 'LEFT', + 'conditions' => $conditions + ); + $queryData['fields'] = am($queryData['fields'], $fields); - $this->__mergeConditions($queryData, $assocData); - if (!in_array($sql, $queryData['joins'])) { - $queryData['joins'][] = $sql; + if (!empty($assocData['order'])) { + $queryData['order'][] = $assocData['order']; + } + if (!in_array($join, $queryData['joins'])) { + $queryData['joins'][] = $join; } return true; } - break; case 'hasMany': - - $conditions = $assocData['conditions']; - $sql = 'SELECT '; - - if ($this->goofyLimit) { - $sql .= $limit; - } - - $sql .= ' ' . join(', ', $this->fields($linkModel, $alias, $assocData['fields'])); - $sql .= ' FROM ' . $this->fullTableName($linkModel) . ' ' . $this->alias . $this->name($alias); - - if (is_array($conditions)) { - $conditions[$alias . '.' . $assocData['foreignKey']] = '{$__cakeID__$}'; - } else { - $cond = $this->name($alias) . '.' . $this->name($assocData['foreignKey']); - $cond .= ' = {$__cakeID__$}'; - if (trim($conditions) != '') { - $conditions .= ' AND '; - } - $conditions .= $cond; - } - - $sql .= $this->conditions($conditions); - $sql .= $this->order($assocData['order']); - - if (!$this->goofyLimit) { - $sql .= $limit; - } - return $sql; + $query = array( + 'conditions' => $this->__mergeConditions(array("{$alias}.{$assocData['foreignKey']}" => '{$__cakeID__$}'), $assocData['conditions']), + 'fields' => $this->fields($linkModel, $alias, $assocData['fields']), + 'table' => $this->fullTableName($linkModel), + 'alias' => $alias, + 'order' => $assocData['order'], + 'limit' => $limit + ); break; case 'hasAndBelongsToMany': $joinTbl = $this->fullTableName($assocData['joinTable']); - $sql = 'SELECT '; - - if ($this->goofyLimit) { - $sql .= $limit; - } $joinFields = array(); + $joinAssoc = null; + $joinAlias = $joinTbl; if (isset($assocData['with']) && !empty($assocData['with'])) { + $joinAssoc = $joinAlias = $model->{$assocData['with']}->name; $joinFields = $model->{$assocData['with']}->loadInfo(); $joinFields = $joinFields->extract('{n}.name'); - if (is_array($joinFields) && !empty($joinFields)) { $joinFields = $this->fields($model->{$assocData['with']}, $model->{$assocData['with']}->name, $joinFields); } } - $sql .= ' ' . join(', ', am($this->fields($linkModel, $alias, $assocData['fields']), $joinFields)); - $sql .= ' FROM ' . $this->fullTableName($linkModel) . ' ' . $this->alias . $this->name($alias); - $sql .= ' JOIN ' . $joinTbl; - $joinAssoc = $joinTbl; - - if (isset($assocData['with']) && !empty($assocData['with'])) { - $joinAssoc = $model->{$assocData['with']}->name; - $sql .= $this->alias . $this->name($joinAssoc); - } - $sql .= ' ON ' . $this->name($joinAssoc); - $sql .= '.' . $this->name($assocData['foreignKey']) . ' = {$__cakeID__$}'; - $sql .= ' AND ' . $this->name($joinAssoc) . '.' . $this->name($assocData['associationForeignKey']); - $sql .= ' = ' . $this->name($alias) . '.' . $this->name($linkModel->primaryKey); - $sql .= $this->conditions($assocData['conditions']); - $sql .= $this->order($assocData['order']); - - if (!$this->goofyLimit) { - $sql .= $limit; - } - return $sql; + $query = array( + 'conditions' => $assocData['conditions'], + 'limit' => $limit, + 'offset' => $assocData['offset'], + 'table' => $this->fullTableName($linkModel), + 'alias' => $alias, + 'fields' => am($this->fields($linkModel, $alias, $assocData['fields']), $joinFields), + 'order' => $assocData['order'], + 'joins' => array(array( + 'table' => $joinTbl, + 'alias' => $joinAssoc, + 'conditions' => array( + array("{$joinAlias}.{$assocData['foreignKey']}" => '{$__cakeID__$}'), + array("{$joinAlias}.{$assocData['associationForeignKey']}" => '{$__cakeIdentifier['."{$alias}.{$linkModel->primaryKey}".']__$}') + )) + ) + ); break; } + if (isset($query)) { + return $this->buildStatement($query, $model); + } return null; } + + function buildJoinStatement($join) { + $data = am(array( + 'type' => null, + 'alias' => null, + 'table' => 'join_table', + 'conditions' => array() + ), $join); + + if (!empty($data['alias'])) { + $data['alias'] = $this->alias . $this->name($data['alias']); + } + if (!empty($data['conditions'])) { + $data['conditions'] = preg_replace('/^\s*WHERE\s*/', '', trim($this->conditions($data['conditions']))); + } + return $this->renderJoinStatement($data); + } + + function buildStatement($query, $model) { + $query = am(array('offset' => null, 'joins' => array()), $query); + if (!empty($query['joins'])) { + for ($i = 0; $i < count($query['joins']); $i++) { + if (is_array($query['joins'][$i])) { + $query['joins'][$i] = $this->buildJoinStatement($query['joins'][$i]); + } + } + } + return $this->renderStatement(array( + 'conditions' => $this->conditions($query['conditions']), + 'fields' => join(', ', $query['fields']), + 'table' => $query['table'], + 'alias' => $this->alias . $this->name($query['alias']), + 'order' => $this->order($query['order']), + 'limit' => $this->limit($query['limit'], $query['offset']), + 'joins' => join(' ', $query['joins']) + )); + } + + function renderJoinStatement($data) { + extract($data); + return trim("{$type} JOIN {$table} {$alias} ON {$conditions}"); + } + + function renderStatement($data) { + extract($data); + return "SELECT {$fields} FROM {$table} {$alias} {$joins} {$conditions} {$order} {$limit}"; + } /** * Private method * * @return array */ - function __mergeConditions(&$queryData, $assocData) { - if (isset($assocData['conditions']) && !empty($assocData['conditions'])) { - if (is_array($queryData['conditions'])) { - $queryData['conditions'] = array_merge((array)$assocData['conditions'], $queryData['conditions']); + function __mergeConditions($query, $assoc) { + if (!empty($assoc)) { + if (is_array($query)) { + return array_merge((array)$assoc, $query); } else { - if (!empty($queryData['conditions'])) { - $queryData['conditions'] = array($queryData['conditions']); - if (is_array($assocData['conditions'])) { - $queryData['conditions'] = array_merge($queryData['conditions'], $assocData['conditions']); + if (!empty($query)) { + $query = array($query); + if (is_array($assoc)) { + $query = array_merge($query, $assoc); } else { - $queryData['conditions'][] = $assocData['conditions']; + $query[] = $assoc; } + return $query; } else { - $queryData['conditions'] = $assocData['conditions']; + return $assoc; } } } + return $query; } /** * Generates and executes an SQL UPDATE statement for given model, fields, and values. @@ -1133,6 +1111,7 @@ class DboSource extends DataSource { */ function update(&$model, $fields = array(), $values = null, $conditions = null) { $updates = array(); + if ($values == null) { $combined = $fields; } else { @@ -1152,11 +1131,16 @@ class DboSource extends DataSource { $updates[] = $update; } } - if ($conditions == null) { - $conditions = array($model->primaryKey => $model->getID()); - } + $conditions = $this->defaultConditions($model, $conditions); - if (!$this->execute('UPDATE '.$this->fullTableName($model).' SET '.join(',', $updates).$this->conditions($conditions))) { + if ($conditions === false) { + return false; + } + $fields = join(',', $updates); + $table = $this->fullTableName($model); + $conditions = $this->conditions($conditions); + + if (!$this->execute("UPDATE {$table} SET {$fields} {$conditions}")) { $model->onError(); return false; } @@ -1170,17 +1154,36 @@ class DboSource extends DataSource { * @return boolean Success */ function delete(&$model, $conditions = null) { - if (empty($model->id) && empty($conditions)) { + $query = $this->defaultConditions($model, $conditions); + + if ($query === false) { return false; - } elseif (empty($conditions)) { - $conditions = array($model->primaryKey => (array)$model->id); } - if ($this->execute('DELETE FROM ' . $this->fullTableName($model) . $this->conditions($conditions)) === false) { + $table = $this->fullTableName($model); + $conditions = $this->conditions($query); + + if ($this->execute("DELETE FROM {$table} {$conditions}") === false) { $model->onError(); return false; } return true; } +/** + * Creates a default set of conditions from the model if $conditions is null/empty. + * + * @param object $model + * @param mixed $conditions + * @return mixed + */ + function defaultConditions(&$model, $conditions) { + if (!empty($conditions)) { + return $conditions; + } + if (!$model->exists()) { + return false; + } + return array($model->primaryKey => (array)$model->getID()); + } /** * Returns a key formatted like a string Model.fieldname(i.e. Post.title, or Country.name) * @@ -1190,10 +1193,9 @@ class DboSource extends DataSource { * @return string */ function resolveKey($model, $key, $assoc = null) { - if ($assoc == null) { + if (empty($assoc)) { $assoc = $model->name; } - if (!strpos('.', $key)) { return $this->name($model->name) . '.' . $this->name($key); } @@ -1214,28 +1216,10 @@ class DboSource extends DataSource { * @param array $data */ function __scrubQueryData(&$data) { - if (!isset($data['conditions'])) { - $data['conditions'] = ' 1 = 1 '; - } - - if (!isset($data['fields'])) { - $data['fields'] = ''; - } - - if (!isset($data['joins'])) { - $data['joins'] = array(); - } - - if (!isset($data['order'])) { - $data['order'] = ''; - } - - if (!isset($data['limit'])) { - $data['limit'] = ''; - } - - if (!isset($data['offset'])) { - $data['offset'] = null; + foreach (array('conditions', 'fields', 'joins', 'order', 'limit', 'offset') as $key) { + if (!isset($data[$key]) || empty($data[$key])) { + $data[$key] = array(); + } } } /** @@ -1244,75 +1228,104 @@ class DboSource extends DataSource { * @param Model $model * @param string $alias Alias tablename * @param mixed $fields + * @param boolean $quote If false, returns fields array unquoted * @return array */ - function fields(&$model, $alias, $fields) { - $resultMatch = null; - $build = true; - if (is_array($fields)) { - $fields = $fields; - } else { - if ($fields != null) { - preg_match_all('/(\\w*\\([\\s\\S]*?\\)[\.,\\s\\w]*?\\))([\\s\\S]*)/', $fields, $result, PREG_PATTERN_ORDER); + function fields(&$model, $alias = null, $fields = array(), $quote = true) { + if (empty($alias)) { + $alias = $model->name; + } - if(isset($result[1][0])){ - $resultMatch = $result[1][0]; + if (!is_array($fields)) { + if (!empty($fields)) { + $depth = 0; + $offset = 0; + $buffer = ''; + $results = array(); + $length = strlen($fields); - if(isset($result[2][0])){ - $fields = $result[2][0]; - - if (preg_match('/AS/i', $fields)) { - $build = false; + while ($offset < $length) { + $tmpOffset = -1; + $offsets = array(strpos($fields, ',', $offset), strpos($fields, '(', $offset), strpos($fields, ')', $offset)); + for ($i = 0; $i < 3; $i++) { + if ($offsets[$i] !== false && ($offsets[$i] < $tmpOffset || $tmpOffset == -1)) { + $tmpOffset = $offsets[$i]; } } - } - if($build === true){ - if (strpos($fields, ',')) { - $fields = explode(',', $fields); + if ($tmpOffset !== -1) { + $buffer .= substr($fields, $offset, ($tmpOffset - $offset)); + if ($fields{$tmpOffset} == ',' && $depth == 0) { + $results[] = $buffer; + $buffer = ''; + } else { + $buffer .= $fields{$tmpOffset}; + } + if ($fields{$tmpOffset} == '(') { + $depth++; + } + if ($fields{$tmpOffset} == ')') { + $depth--; + } + $offset = ++$tmpOffset; } else { - $fields = array($fields); + $results[] = $buffer . substr($fields, $offset); + $offset = $length; } - $fields = array_map('trim', $fields); } - } else { - foreach($model->_tableInfo->value as $field) { - $fields[] = $field['name']; + + if (!empty($results)) { + $fields = array_map('trim', $results); + } else { + $fields = array(); } } } - if($build === true){ - $count = count($fields); - if ($count >= 1 && $fields[0] != '*') { - for($i = 0; $i < $count; $i++) { - if (!preg_match('/^.+\\(.*\\)/', $fields[$i])) { - $prepend = ''; + if (empty($fields)) { + $fieldData = $model->loadInfo(); + $fields = $fieldData->extract('{n}.name'); + } else { + $fields = array_filter($fields); + } + if (!$quote) { + return $fields; + } + $count = count($fields); - if (strpos($fields[$i], 'DISTINCT') !== false) { - $prepend = 'DISTINCT '; - $fields[$i] = trim(r('DISTINCT', '', $fields[$i])); - } + if ($count >= 1 && $fields[0] != '*') { + for($i = 0; $i < $count; $i++) { + if (!preg_match('/^.+\\(.*\\)/', $fields[$i])) { + $prepend = ''; - $dot = strrpos($fields[$i], '.'); + if (strpos($fields[$i], 'DISTINCT') !== false) { + $prepend = 'DISTINCT '; + $fields[$i] = trim(r('DISTINCT', '', $fields[$i])); + } + $dot = strrpos($fields[$i], '.'); - if ($dot === false) { - $fields[$i] = $prepend . $this->name($alias) . '.' . $this->name($fields[$i]); - } else { - $build = explode('.', $fields[$i]); + if ($dot === false) { + $fields[$i] = $prepend . $this->name($alias) . '.' . $this->name($fields[$i]); + } else { + $build = explode('.', $fields[$i]); + if (!Set::numeric($build)) { $fields[$i] = $prepend . $this->name($build[0]) . '.' . $this->name($build[1]); } } + } elseif (preg_match('/\(([\.\w]+)\)/', $fields[$i], $field)) { + if (isset($field[1])) { + if (strrpos($field[1], '.') === false) { + $field[1] = $this->name($alias) . '.' . $this->name($field[1]); + } else { + $field[0] = explode('.', $field[1]); + if (!Set::numeric($field[0])) { + $field[0] = join('.', array_map(array($this, 'name'), $field[0])); + $fields[$i] = preg_replace('/\(' . $field[1] . '\)/', '(' . $field[0] . ')', $fields[$i], 1); + } + } + } } } } - - if($resultMatch != null){ - if(is_string($fields)) { - $fields = array($resultMatch . $fields); - } else { - $fields = array_merge(array($resultMatch), $fields); - } - } return $fields; } /** @@ -1321,17 +1334,15 @@ class DboSource extends DataSource { * @param mixed $conditions Array or string of conditions * @return string SQL fragment */ - function conditions($conditions) { - $clause = ''; - if (!is_array($conditions)) { + function conditions($conditions, $quoteValues = true) { + $clause = $out = ''; + if (is_string($conditions) || empty($conditions) || $conditions === true) { + if (empty($conditions) || trim($conditions) == '' || $conditions === true) { + return ' WHERE 1 = 1'; + } if (!preg_match('/^WHERE\\x20|^GROUP\\x20BY\\x20|^HAVING\\x20|^ORDER\\x20BY\\x20/i', $conditions, $match)) { $clause = ' WHERE '; } - } - - if ($conditions === true) { - return $clause . ' 1 = 1'; - } elseif (is_string($conditions)) { if (trim($conditions) == '') { $conditions = ' 1 = 1'; } else { @@ -1353,9 +1364,7 @@ class DboSource extends DataSource { for($i = 0; $i < $pregCount; $i++) { if (!empty($match['1'][$i]) && !is_numeric($match['1'][$i])) { - $conditions = $conditions . ' '; - $match['0'][$i] = preg_replace('/\\./', '\\.', $match['0'][$i]); - $conditions = preg_replace('/^' . $match['0'][$i] . '(?=[^\\w])/', ' '.$this->name($match['1'][$i]), $conditions); + $conditions = preg_replace('/^' . $match['0'][$i] . '(?=[^\\w])/', ' ' . $this->name($match['1'][$i]), $conditions . ' '); if (strpos($conditions, '(' . $match['0'][$i]) === false) { $conditions = preg_replace('/[^\w]' . $match['0'][$i] . '(?=[^\\w])/', ' '.$this->name($match['1'][$i]), $conditions); } else { @@ -1370,12 +1379,12 @@ class DboSource extends DataSource { } else { $clause = ' WHERE '; if (!empty($conditions)) { - $out = $this->conditionKeysToString($conditions); + $out = $this->conditionKeysToString($conditions, $quoteValues); } if (empty($out) || empty($conditions)) { return $clause . ' 1 = 1'; } - return $clause . ' (' . join(') AND (', $out) . ')'; + return $clause . join(' AND ', $out); } } /** @@ -1384,7 +1393,7 @@ class DboSource extends DataSource { * @param array $conditions Array or string of conditions * @return string SQL fragment */ - function conditionKeysToString($conditions) { + function conditionKeysToString($conditions, $quoteValues = true) { $c = 0; $data = null; $out = array(); @@ -1392,16 +1401,21 @@ class DboSource extends DataSource { $join = ' AND '; foreach($conditions as $key => $value) { + if (is_numeric($key) && empty($value)) { + continue; + } if (in_array(strtolower(trim($key)), $bool)) { $join = ' ' . strtoupper($key) . ' '; - $value = $this->conditionKeysToString($value); + $value = $this->conditionKeysToString($value, $quoteValues); if (strpos($join, 'NOT') !== false) { $out[] = 'NOT (' . join(') ' . strtoupper($key) . ' (', $value) . ')'; } else { $out[] = '(' . join(') ' . strtoupper($key) . ' (', $value) . ')'; } } else { - if (is_array($value) && !empty($value)) { + if (is_string($value) && preg_match('/^\{\$__cakeIdentifier\[(.*)\]__\$}$/', $value, $identifier) && isset($identifier[1])) { + $data .= $this->name($key) . ' = ' . $this->name($identifier[1]); + } elseif (is_array($value) && !empty($value)) { $keys = array_keys($value); if ($keys[0] === 0) { $data = $this->name($key) . ' IN ('; @@ -1410,21 +1424,23 @@ class DboSource extends DataSource { $data .= $value[0]; $data .= ')'; } else { - foreach($value as $valElement) { - $data .= $this->value($valElement) . ', '; + if ($quoteValues) { + foreach($value as $valElement) { + $data .= $this->value($valElement) . ', '; + } } $data[strlen($data) - 2] = ')'; } } else { - $out[] = '(' . join(') AND (', $this->conditionKeysToString($value)) . ')'; + $out[] = '(' . join(') AND (', $this->conditionKeysToString($value, $quoteValues)) . ')'; } - } elseif(is_numeric($key)) { + } elseif (is_numeric($key)) { $data = ' ' . $value; - } elseif($value === null || (is_array($value) && empty($value))) { + } elseif ($value === null || (is_array($value) && empty($value))) { $data = $this->name($key) . ' IS NULL'; - } elseif($value === '') { + } elseif ($value === '') { $data = $this->name($key) . " = ''"; - } elseif (preg_match('/^([a-z]*\\([a-z0-9]*\\)\\x20?|(?:' . join('\\x20)|(?:', $this->__sqlOps) . '\\x20)|<[>=]?(?![^>]+>)\\x20?|[>=!]{1,3}(?!<)\\x20?)?(.*)/i', $value, $match)) { + } elseif (preg_match('/^([a-z]*\\([a-z0-9]*\\)\\x20?|(?:' . join('\\x20)|(?:', $this->__sqlOps) . '\\x20)|<=?(?![^>]+>)\\x20?|[>=!]{1,3}(?!<)\\x20?)?(.*)/i', $value, $match)) { if (preg_match('/(\\x20[\\w]*\\x20)/', $key, $regs)) { $clause = $regs['1']; $key = preg_replace('/' . $regs['1'] . '/', '', $key); @@ -1442,8 +1458,10 @@ class DboSource extends DataSource { $match['2'] = str_replace('-!', '', $match['2']); $data = $this->name($key) . ' ' . $match['1'] . ' ' . $match['2']; } else { - $match['2'] = $this->value($match['2']); - $match['2'] = str_replace(' AND ', "' AND '", $match['2']); + if (!empty($match['2']) && $quoteValues) { + $match['2'] = $this->value($match['2']); + $match['2'] = str_replace(' AND ', "' AND '", $match['2']); + } $data = $this->name($key) . ' ' . $match['1'] . ' ' . $match['2']; } } @@ -1585,24 +1603,6 @@ class DboSource extends DataSource { } $this->disconnect(); } -/** - * To-be-overridden in subclasses. - * - */ - function buildSchemaQuery($schema) { - die (__("Implement in DBO")); - } -/** - * Destructor. Closes connection to the database. - * - */ - function __destruct() { - if ($this->_transactionStarted) { - $this->rollback(); - } - $this->close(); - parent::__destruct(); - } /** * Checks if the specified table contains any record matching specified SQL * @@ -1612,7 +1612,7 @@ class DboSource extends DataSource { */ function hasAny($model, $sql) { $sql = $this->conditions($sql); - $out = $this->fetchRow("SELECT COUNT(*) " . $this->alias . "count FROM " . $this->fullTableName($model) . ' ' . ($sql ? ' ' . $sql : 'WHERE 1 = 1')); + $out = $this->fetchRow("SELECT COUNT(" . $model->primaryKey . ") " . $this->alias . "count FROM " . $this->fullTableName($model) . ' ' . ($sql ? ' ' . $sql : 'WHERE 1 = 1')); if (is_array($out)) { return $out[0]['count']; @@ -1621,22 +1621,6 @@ class DboSource extends DataSource { } } /** - * Gets the 'meta' definition of the given database table, where $model is either - * a model object, or the full table name. - * - * @param mixed $model - * @return array - */ - function getDefinition($model) { - if (is_string($model)) { - $table = $model; - } else { - $table = $this->fullTableName($model, false); - } - - - } -/** * Translates between PHP boolean values and Database (faked) boolean values * * @param mixed $data Value to be translated @@ -1656,5 +1640,17 @@ class DboSource extends DataSource { return false; } } +/** + * Destructor. Closes connection to the database. + * + */ + function __destruct() { + if ($this->_transactionStarted) { + $this->rollback(); + } + $this->close(); + parent::__destruct(); + } } -?> + +?> \ No newline at end of file diff --git a/cake/tests/cases/libs/model/datasources/dbo_source.test.php b/cake/tests/cases/libs/model/datasources/dbo_source.test.php index 33858b4f1..2a237323a 100644 --- a/cake/tests/cases/libs/model/datasources/dbo_source.test.php +++ b/cake/tests/cases/libs/model/datasources/dbo_source.test.php @@ -261,6 +261,7 @@ class DboSourceTest extends UnitTestCase { require_once r('//', '/', APP) . 'config/database.php'; $config = new DATABASE_CONFIG(); $this->db =& new DboTest($config->default); + $this->db->fullDebug = false; $this->model = new TestModel(); } @@ -273,8 +274,8 @@ class DboSourceTest extends UnitTestCase { $this->model = new TestModel4(); $this->model->loadInfo(); $this->_buildRelatedModels($this->model); - - $binding = array('type'=>'belongsTo', 'model'=>'TestModel4Parent'); + + $binding = array('type' => 'belongsTo', 'model' => 'TestModel4Parent'); $queryData = array(); $resultSet = null; $null = null; @@ -282,9 +283,10 @@ class DboSourceTest extends UnitTestCase { $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); - $this->assertTrue($result); - + + $this->assertPattern('/^SELECT\s+`TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`, `TestModel4Parent`\.`id`, `TestModel4Parent`\.`name`, `TestModel4Parent`\.`created`, `TestModel4Parent`\.`updated`\s+/', $queryData['selfJoin'][0]); + $this->assertPattern('/FROM\s+/', $queryData['selfJoin'][0]); $expected = 'SELECT '; $expected .= '`TestModel4`.`id`, `TestModel4`.`name`, `TestModel4`.`created`, `TestModel4`.`updated`, `TestModel4Parent`.`id`, `TestModel4Parent`.`name`, `TestModel4Parent`.`created`, `TestModel4Parent`.`updated`'; $expected .= ' FROM '; @@ -297,327 +299,206 @@ class DboSourceTest extends UnitTestCase { $this->assertEqual($queryData['selfJoin'][0], $expected); $result = $this->db->generateAssociationQuery($this->model, $null, null, null, null, $queryData, false, $null); - - $expected = 'SELECT '; - $expected .= '`TestModel4`.`id`, `TestModel4`.`name`, `TestModel4`.`created`, `TestModel4`.`updated`, `TestModel4Parent`.`id`, `TestModel4Parent`.`name`, `TestModel4Parent`.`created`, `TestModel4Parent`.`updated`'; - $expected .= ' FROM '; - $expected .= '`test_model4` AS `TestModel4`'; - $expected .= ' LEFT JOIN '; - $expected .= '`test_model4` AS `TestModel4Parent`'; - $expected .= ' ON '; - $expected .= '`TestModel4`.`parent_id` = `TestModel4Parent`.`id`'; - $expected .= ' WHERE '; - $expected .= '1 = 1'; - $expected .= ' '; - - $this->assertEqual($result, $expected); + $this->assertPattern('/^SELECT\s+`TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`, `TestModel4Parent`\.`id`, `TestModel4Parent`\.`name`, `TestModel4Parent`\.`created`, `TestModel4Parent`\.`updated`\s+/', $result); + $this->assertPattern('/FROM\s+`test_model4` AS `TestModel4`\s+LEFT JOIN\s+`test_model4` AS `TestModel4Parent`/', $result); + $this->assertPattern('/\s+ON\s+`TestModel4`.`parent_id` = `TestModel4Parent`.`id`\s+WHERE/', $result); + $this->assertPattern('/\s+WHERE\s+1 = 1\s+$/', $result); } - + function testGenerateAssociationQuerySelfJoinWithConditions() { $this->model = new TestModel4(); $this->model->loadInfo(); $this->_buildRelatedModels($this->model); - - $binding = array('type'=>'belongsTo', 'model'=>'TestModel4Parent'); + + $binding = array('type' => 'belongsTo', 'model' => 'TestModel4Parent'); $queryData = array('conditions' => array('TestModel4Parent.name' => '!= mariano')); $resultSet = null; $null = null; - + $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); - + $this->assertTrue($result); $result = $this->db->generateAssociationQuery($this->model, $null, null, null, null, $queryData, false, $null); - - $expected = 'SELECT '; - $expected .= '`TestModel4`.`id`, `TestModel4`.`name`, `TestModel4`.`created`, `TestModel4`.`updated`, `TestModel4Parent`.`id`, `TestModel4Parent`.`name`, `TestModel4Parent`.`created`, `TestModel4Parent`.`updated`'; - $expected .= ' FROM '; - $expected .= '`test_model4` AS `TestModel4`'; - $expected .= ' LEFT JOIN '; - $expected .= '`test_model4` AS `TestModel4Parent`'; - $expected .= ' ON '; - $expected .= '`TestModel4`.`parent_id` = `TestModel4Parent`.`id`'; - $expected .= ' WHERE '; - $expected .= '(`TestModel4Parent`.`name` != \'mariano\')'; - $expected .= ' '; - - $this->assertEqual($result, $expected); + $this->assertPattern('/^SELECT\s+`TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`, `TestModel4Parent`\.`id`, `TestModel4Parent`\.`name`, `TestModel4Parent`\.`created`, `TestModel4Parent`\.`updated`\s+/', $result); + $this->assertPattern('/FROM\s+`test_model4` AS `TestModel4`\s+LEFT JOIN\s+`test_model4` AS `TestModel4Parent`/', $result); + $this->assertPattern('/\s+ON\s+`TestModel4`.`parent_id` = `TestModel4Parent`.`id`\s+WHERE/', $result); + $this->assertPattern('/\s+WHERE\s+(?:\()?`TestModel4Parent`.`name`\s+!=\s+\'mariano\'(?:\))?\s*$/', $result); } - + function testGenerateAssociationQueryHasOne() { $this->model = new TestModel4(); $this->model->loadInfo(); $this->_buildRelatedModels($this->model); - - $binding = array('type'=>'hasOne', 'model'=>'TestModel5'); - + + $binding = array('type' => 'hasOne', 'model' => 'TestModel5'); + $queryData = array(); $resultSet = null; $null = null; - + $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); - $this->assertTrue($result); - + + $result = $this->db->buildJoinStatement($queryData['joins'][0]); $expected = ' LEFT JOIN `test_model5` AS `TestModel5` ON `TestModel5`.`test_model4_id` = `TestModel4`.`id`'; - - $this->assertEqual($queryData['joins'][0], $expected); - + $this->assertEqual(trim($result), trim($expected)); + $result = $this->db->generateAssociationQuery($this->model, $null, null, null, null, $queryData, false, $null); - - $expected = 'SELECT '; - $expected .= '`TestModel4`.`id`, `TestModel4`.`name`, `TestModel4`.`created`, `TestModel4`.`updated`'; - $expected .= ', '; - $expected .= '`TestModel5`.`id`, `TestModel5`.`test_model4_id`, `TestModel5`.`name`, `TestModel5`.`created`, `TestModel5`.`updated`'; - $expected .= ' FROM '; - $expected .= '`test_model4` AS `TestModel4`'; - $expected .= ' LEFT JOIN '; - $expected .= '`test_model5` AS `TestModel5`'; - $expected .= ' ON '; - $expected .= '`TestModel5`.`test_model4_id` = `TestModel4`.`id`'; - $expected .= ' WHERE '; - $expected .= '( 1 = 1 ) AND ( 1 = 1 )'; - $expected .= ' '; - - $this->assertEqual($result, $expected); + $this->assertPattern('/^SELECT\s+`TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`, `TestModel5`\.`id`, `TestModel5`\.`test_model4_id`, `TestModel5`\.`name`, `TestModel5`\.`created`, `TestModel5`\.`updated`\s+/', $result); + $this->assertPattern('/\s+FROM\s+`test_model4` AS `TestModel4`\s+LEFT JOIN\s+/', $result); + $this->assertPattern('/`test_model5` AS `TestModel5`\s+ON\s+`TestModel5`.`test_model4_id` = `TestModel4`.`id`\s+WHERE/', $result); + $this->assertPattern('/\s+WHERE\s+(?:\()?\s*1 = 1\s*(?:\))?\s*$/', $result); } - + function testGenerateAssociationQueryHasOneWithConditions() { $this->model = new TestModel4(); $this->model->loadInfo(); $this->_buildRelatedModels($this->model); - - $binding = array('type'=>'hasOne', 'model'=>'TestModel5'); - + + $binding = array('type' => 'hasOne', 'model' => 'TestModel5'); + $queryData = array('conditions' => array('TestModel5.name' => '!= mariano')); $resultSet = null; $null = null; - + $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); - $this->assertTrue($result); - + $result = $this->db->generateAssociationQuery($this->model, $null, null, null, null, $queryData, false, $null); - - $expected = 'SELECT '; - $expected .= '`TestModel4`.`id`, `TestModel4`.`name`, `TestModel4`.`created`, `TestModel4`.`updated`'; - $expected .= ', '; - $expected .= '`TestModel5`.`id`, `TestModel5`.`test_model4_id`, `TestModel5`.`name`, `TestModel5`.`created`, `TestModel5`.`updated`'; - $expected .= ' FROM '; - $expected .= '`test_model4` AS `TestModel4`'; - $expected .= ' LEFT JOIN '; - $expected .= '`test_model5` AS `TestModel5`'; - $expected .= ' ON '; - $expected .= '`TestModel5`.`test_model4_id` = `TestModel4`.`id`'; - $expected .= ' WHERE '; - $expected .= '( 1 = 1 )'; - $expected .= ' AND '; - $expected .= '(`TestModel5`.`name` != \'mariano\')'; - $expected .= ' '; - - $this->assertEqual($result, $expected); + $this->assertPattern('/^SELECT\s+`TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`, `TestModel5`\.`id`, `TestModel5`\.`test_model4_id`, `TestModel5`\.`name`, `TestModel5`\.`created`, `TestModel5`\.`updated`\s+/', $result); + $this->assertPattern('/\s+FROM\s+`test_model4` AS `TestModel4`\s+LEFT JOIN\s+`test_model5` AS `TestModel5`/', $result); + $this->assertPattern('/\s+ON\s+`TestModel5`.`test_model4_id` = `TestModel4`.`id`\s+WHERE/', $result); + $this->assertPattern('/\s+WHERE\s+(?:\()?\s*`TestModel5`.`name`\s+!=\s+\'mariano\'\s*(?:\))?\s*$/', $result); } - + function testGenerateAssociationQueryBelongsTo() { $this->model = new TestModel5(); $this->model->loadInfo(); $this->_buildRelatedModels($this->model); - + $binding = array('type'=>'belongsTo', 'model'=>'TestModel4'); $queryData = array(); $resultSet = null; $null = null; - + $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); - $this->assertTrue($result); - + + $result = $this->db->buildJoinStatement($queryData['joins'][0]); $expected = ' LEFT JOIN `test_model4` AS `TestModel4` ON `TestModel5`.`test_model4_id` = `TestModel4`.`id`'; - - $this->assertEqual($queryData['joins'][0], $expected); - + $this->assertEqual(trim($result), trim($expected)); + $result = $this->db->generateAssociationQuery($this->model, $null, null, null, null, $queryData, false, $null); - - $expected = 'SELECT '; - $expected .= '`TestModel5`.`id`, `TestModel5`.`test_model4_id`, `TestModel5`.`name`, `TestModel5`.`created`, `TestModel5`.`updated`'; - $expected .= ', '; - $expected .= '`TestModel4`.`id`, `TestModel4`.`name`, `TestModel4`.`created`, `TestModel4`.`updated`'; - $expected .= ' FROM '; - $expected .= '`test_model5` AS `TestModel5`'; - $expected .= ' LEFT JOIN '; - $expected .= '`test_model4` AS `TestModel4`'; - $expected .= ' ON '; - $expected .= '`TestModel5`.`test_model4_id` = `TestModel4`.`id`'; - $expected .= ' WHERE '; - $expected .= '( 1 = 1 ) AND ( 1 = 1 )'; - $expected .= ' '; - - $this->assertEqual($result, $expected); + $this->assertPattern('/^SELECT\s+`TestModel5`\.`id`, `TestModel5`\.`test_model4_id`, `TestModel5`\.`name`, `TestModel5`\.`created`, `TestModel5`\.`updated`, `TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`\s+/', $result); + $this->assertPattern('/\s+FROM\s+`test_model5` AS `TestModel5`\s+LEFT JOIN\s+`test_model4` AS `TestModel4`/', $result); + $this->assertPattern('/\s+ON\s+`TestModel5`.`test_model4_id` = `TestModel4`.`id`\s+WHERE\s+/', $result); + $this->assertPattern('/\s+WHERE\s+(?:\()?\s*1 = 1\s*(?:\))?\s*$/', $result); } - + function testGenerateAssociationQueryBelongsToWithConditions() { $this->model = new TestModel5(); $this->model->loadInfo(); $this->_buildRelatedModels($this->model); - - $binding = array('type'=>'belongsTo', 'model'=>'TestModel4'); + + $binding = array('type' => 'belongsTo', 'model' => 'TestModel4'); $queryData = array('conditions' => array('TestModel5.name' => '!= mariano')); $resultSet = null; $null = null; - + $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); - $this->assertTrue($result); - + + $result = $this->db->buildJoinStatement($queryData['joins'][0]); $expected = ' LEFT JOIN `test_model4` AS `TestModel4` ON `TestModel5`.`test_model4_id` = `TestModel4`.`id`'; - - $this->assertEqual($queryData['joins'][0], $expected); - + $this->assertEqual(trim($result), trim($expected)); + $result = $this->db->generateAssociationQuery($this->model, $null, null, null, null, $queryData, false, $null); - - $expected = 'SELECT '; - $expected .= '`TestModel5`.`id`, `TestModel5`.`test_model4_id`, `TestModel5`.`name`, `TestModel5`.`created`, `TestModel5`.`updated`'; - $expected .= ', '; - $expected .= '`TestModel4`.`id`, `TestModel4`.`name`, `TestModel4`.`created`, `TestModel4`.`updated`'; - $expected .= ' FROM '; - $expected .= '`test_model5` AS `TestModel5`'; - $expected .= ' LEFT JOIN '; - $expected .= '`test_model4` AS `TestModel4`'; - $expected .= ' ON '; - $expected .= '`TestModel5`.`test_model4_id` = `TestModel4`.`id`'; - $expected .= ' WHERE '; - $expected .= '( 1 = 1 ) AND (`TestModel5`.`name` != \'mariano\')'; - $expected .= ' '; - - $this->assertEqual($result, $expected); + $this->assertPattern('/^SELECT\s+`TestModel5`\.`id`, `TestModel5`\.`test_model4_id`, `TestModel5`\.`name`, `TestModel5`\.`created`, `TestModel5`\.`updated`, `TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`\s+/', $result); + $this->assertPattern('/\s+FROM\s+`test_model5` AS `TestModel5`\s+LEFT JOIN\s+`test_model4` AS `TestModel4`/', $result); + $this->assertPattern('/\s+ON\s+`TestModel5`.`test_model4_id` = `TestModel4`.`id`\s+WHERE\s+/', $result); + $this->assertPattern('/\s+WHERE\s+`TestModel5`.`name` != \'mariano\'\s*$/', $result); } - + function testGenerateAssociationQueryHasMany() { $this->model = new TestModel5(); $this->model->loadInfo(); $this->_buildRelatedModels($this->model); - - $binding = array('type'=>'hasMany', 'model'=>'TestModel6'); + + $binding = array('type' => 'hasMany', 'model' => 'TestModel6'); $queryData = array(); $resultSet = null; $null = null; - + $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); - - $expected = 'SELECT '; - $expected .= '`TestModel6`.`id`, `TestModel6`.`test_model5_id`, `TestModel6`.`name`, `TestModel6`.`created`, `TestModel6`.`updated`'; - $expected .= ' FROM '; - $expected .= '`test_model6` AS `TestModel6`'; - $expected .= ' WHERE '; - $expected .= '1 = 1'; - $expected .= ' AND '; - $expected .= '`TestModel6`.`test_model5_id` = {$__cakeID__$}'; - - $this->assertEqual($result, $expected); - + $this->assertPattern('/^SELECT\s+`TestModel6`\.`id`, `TestModel6`\.`test_model5_id`, `TestModel6`\.`name`, `TestModel6`\.`created`, `TestModel6`\.`updated`\s+/', $result); + $this->assertPattern('/\s+FROM\s+`test_model6` AS `TestModel6`\s+WHERE/', $result); + $this->assertPattern('/\s+WHERE\s+`TestModel6`.`test_model5_id`\s+=\s+{\$__cakeID__\$}/', $result); + $result = $this->db->generateAssociationQuery($this->model, $null, null, null, null, $queryData, false, $null); - - $expected = 'SELECT '; - $expected .= '`TestModel5`.`id`, `TestModel5`.`test_model4_id`, `TestModel5`.`name`, `TestModel5`.`created`, `TestModel5`.`updated`'; - $expected .= ' FROM '; - $expected .= '`test_model5` AS `TestModel5`'; - $expected .= ' WHERE '; - $expected .= '1 = 1'; - $expected .= ' '; - - $this->assertEqual($result, $expected); + $this->assertPattern('/^SELECT\s+`TestModel5`\.`id`, `TestModel5`\.`test_model4_id`, `TestModel5`\.`name`, `TestModel5`\.`created`, `TestModel5`\.`updated`\s+/', $result); + $this->assertPattern('/\s+FROM\s+`test_model5` AS `TestModel5`\s+WHERE\s+/', $result); + $this->assertPattern('/\s+WHERE\s+(?:\()?\s*1 = 1\s*(?:\))?\s*$/', $result); } - + function testGenerateAssociationQueryHasManyWithConditions() { $this->model = new TestModel5(); $this->model->loadInfo(); $this->_buildRelatedModels($this->model); - - $binding = array('type'=>'hasMany', 'model'=>'TestModel6'); + + $binding = array('type' => 'hasMany', 'model' => 'TestModel6'); $queryData = array('conditions' => array('TestModel5.name' => '!= mariano')); $resultSet = null; $null = null; - + $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); - - $expected = 'SELECT '; - $expected .= '`TestModel6`.`id`, `TestModel6`.`test_model5_id`, `TestModel6`.`name`, `TestModel6`.`created`, `TestModel6`.`updated`'; - $expected .= ' FROM '; - $expected .= '`test_model6` AS `TestModel6`'; - $expected .= ' WHERE '; - $expected .= '1 = 1'; - $expected .= ' AND '; - $expected .= '`TestModel6`.`test_model5_id` = {$__cakeID__$}'; - - $this->assertEqual($result, $expected); - + $this->assertPattern('/^SELECT\s+`TestModel6`\.`id`, `TestModel6`\.`test_model5_id`, `TestModel6`\.`name`, `TestModel6`\.`created`, `TestModel6`\.`updated`\s+/', $result); + $this->assertPattern('/\s+FROM\s+`test_model6` AS `TestModel6`\s+WHERE\s+/', $result); + $this->assertPattern('/WHERE\s+(?:\()?`TestModel6`\.`test_model5_id`\s+=\s+{\$__cakeID__\$}(?:\))?/', $result); + $result = $this->db->generateAssociationQuery($this->model, $null, null, null, null, $queryData, false, $null); - - $expected = 'SELECT '; - $expected .= '`TestModel5`.`id`, `TestModel5`.`test_model4_id`, `TestModel5`.`name`, `TestModel5`.`created`, `TestModel5`.`updated`'; - $expected .= ' FROM '; - $expected .= '`test_model5` AS `TestModel5`'; - $expected .= ' WHERE '; - $expected .= '(`TestModel5`.`name` != \'mariano\')'; - $expected .= ' '; - - $this->assertEqual($result, $expected); + $this->assertPattern('/^SELECT\s+`TestModel5`\.`id`, `TestModel5`\.`test_model4_id`, `TestModel5`\.`name`, `TestModel5`\.`created`, `TestModel5`\.`updated`\s+/', $result); + $this->assertPattern('/\s+FROM\s+`test_model5` AS `TestModel5`\s+WHERE\s+/', $result); + $this->assertPattern('/\s+WHERE\s+(?:\()?`TestModel5`.`name`\s+!=\s+\'mariano\'(?:\))?\s*$/', $result); } - + function testGenerateAssociationQueryHasAndBelongsToMany() { $this->model = new TestModel4(); $this->model->loadInfo(); $this->_buildRelatedModels($this->model); - - $binding = array('type'=>'hasAndBelongsToMany', 'model'=>'TestModel7'); + + $binding = array('type' => 'hasAndBelongsToMany', 'model' => 'TestModel7'); $queryData = array(); $resultSet = null; $null = null; - + $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); - - $expected = 'SELECT '; - $expected .= '`TestModel7`.`id`, `TestModel7`.`name`, `TestModel7`.`created`, `TestModel7`.`updated`'; - $expected .= ' FROM '; - $expected .= '`test_model7` AS `TestModel7`'; - $expected .= ' JOIN '; - $expected .= '`test_model4_test_model7`'; - $expected .= ' ON '; - $expected .= '`test_model4_test_model7`.`test_model4_id` = {$__cakeID__$}'; - $expected .= ' AND '; - $expected .= '`test_model4_test_model7`.`test_model7_id` = `TestModel7`.`id`'; - $expected .= ' WHERE '; - $expected .= '1 = 1 '; - - $this->assertEqual($result, $expected); - + $this->assertPattern('/^SELECT\s+`TestModel7`\.`id`, `TestModel7`\.`name`, `TestModel7`\.`created`, `TestModel7`\.`updated`\s+/', $result); + $this->assertPattern('/\s+FROM\s+`test_model7` AS `TestModel7`\s+JOIN\s+`test_model4_test_model7`/', $result); + $this->assertPattern('/\s+ON\s+(?:\()?`test_model4_test_model7`\.`test_model4_id`\s+=\s+{\$__cakeID__\$}(?:\))?/', $result); + $this->assertPattern('/\s+AND\s+(?:\()?`test_model4_test_model7`\.`test_model7_id`\s+=\s+`TestModel7`\.`id`(?:\))?/', $result); + $this->assertPattern('/WHERE\s+(?:\()?1 = 1(?:\))?\s*$/', $result); + $result = $this->db->generateAssociationQuery($this->model, $null, null, null, null, $queryData, false, $null); - - $expected = 'SELECT '; - $expected .= '`TestModel4`.`id`, `TestModel4`.`name`, `TestModel4`.`created`, `TestModel4`.`updated`'; - $expected .= ' FROM '; - $expected .= '`test_model4` AS `TestModel4`'; - $expected .= ' WHERE '; - $expected .= '1 = 1'; - $expected .= ' '; - - $this->assertEqual($result, $expected); + $this->assertPattern('/^SELECT\s+`TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`\s+/', $result); + $this->assertPattern('/\s+FROM\s+`test_model4` AS `TestModel4`\s+WHERE/', $result); + $this->assertPattern('/\s+WHERE\s+(?:\()?1 = 1(?:\))?\s*$/', $result); } function testGenerateAssociationQueryHasAndBelongsToManyWithConditions() { @@ -633,35 +514,16 @@ class DboSourceTest extends UnitTestCase { $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); - - $expected = 'SELECT '; - $expected .= '`TestModel7`.`id`, `TestModel7`.`name`, `TestModel7`.`created`, `TestModel7`.`updated`'; - $expected .= ' FROM '; - $expected .= '`test_model7` AS `TestModel7`'; - $expected .= ' JOIN '; - $expected .= '`test_model4_test_model7`'; - $expected .= ' ON '; - $expected .= '`test_model4_test_model7`.`test_model4_id` = {$__cakeID__$}'; - $expected .= ' AND '; - $expected .= '`test_model4_test_model7`.`test_model7_id` = `TestModel7`.`id`'; - $expected .= ' WHERE '; - $expected .= '1 = 1 '; - - $this->assertEqual($result, $expected); - + $this->assertPattern('/^SELECT\s+`TestModel7`\.`id`, `TestModel7`\.`name`, `TestModel7`\.`created`, `TestModel7`\.`updated`\s+/', $result); + $this->assertPattern('/\s+FROM\s+`test_model7` AS `TestModel7`\s+JOIN\s+`test_model4_test_model7`+/', $result); + $this->assertPattern('/\s+ON\s+(?:\()`test_model4_test_model7`\.`test_model4_id`\s+=\s+{\$__cakeID__\$}(?:\))?/', $result); + $this->assertPattern('/\s+AND\s+(?:\()`test_model4_test_model7`\.`test_model7_id`\s+=\s+`TestModel7`.`id`(?:\))?\s+WHERE\s+/', $result); + $result = $this->db->generateAssociationQuery($this->model, $null, null, null, null, $queryData, false, $null); - - $expected = 'SELECT '; - $expected .= '`TestModel4`.`id`, `TestModel4`.`name`, `TestModel4`.`created`, `TestModel4`.`updated`'; - $expected .= ' FROM '; - $expected .= '`test_model4` AS `TestModel4`'; - $expected .= ' WHERE '; - $expected .= '(`TestModel4`.`name` != \'mariano\')'; - $expected .= ' '; - - $this->assertEqual($result, $expected); + $this->assertPattern('/^SELECT\s+`TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`\s+/', $result); + $this->assertPattern('/\s+FROM\s+`test_model4` AS `TestModel4`\s+WHERE\s+(?:\()?`TestModel4`.`name`\s+!=\s+\'mariano\'(?:\))?\s*$/', $result); } - + function _buildRelatedModels(&$model) { foreach($model->__associations as $type) { foreach($model->{$type} as $assoc => $assocData) { @@ -675,7 +537,7 @@ class DboSourceTest extends UnitTestCase { } } } - + function &_prepareAssociationQuery(&$model, &$queryData, $binding) { $type = $binding['type']; $assoc = $binding['model']; @@ -694,7 +556,6 @@ class DboSourceTest extends UnitTestCase { 'assocData'=> $assocData, 'external'=> $external ); - return $result; } @@ -711,17 +572,17 @@ class DboSourceTest extends UnitTestCase { $expected = " WHERE `Post`.`title` = '1.1'"; $this->assertEqual($result, $expected); - /* + $result = $this->db->conditions("User.id != 0 AND User.user LIKE '%arr%'"); + $expected = " WHERE `User`.`id` != 0 AND `User`.`user` LIKE '%arr%'"; + $this->assertEqual($result, $expected); + $result = $this->db->conditions("SUM(Post.comments_count) > 500"); $expected = " WHERE SUM( `Post`.`comments_count`) > 500"; $this->assertEqual($result, $expected); - */ - /* $result = $this->db->conditions("(Post.created < '" . date('Y-m-d H:i:s') . "') GROUP BY YEAR(Post.created), MONTH(Post.created)"); $expected = " WHERE ( `Post`.`created` < '" . date('Y-m-d H:i:s') . "') GROUP BY YEAR( `Post`.`created`), MONTH( `Post`.`created`)"; $this->assertEqual($result, $expected); - */ $result = $this->db->conditions("score BETWEEN 90.1 AND 95.7"); $expected = " WHERE score BETWEEN 90.1 AND 95.7"; @@ -731,37 +592,30 @@ class DboSourceTest extends UnitTestCase { $expected = " WHERE `Aro`.`rght` = `Aro`.`lft` + 1.1"; $this->assertEqual($result, $expected); - /* $result = $this->db->conditions("(Post.created < '" . date('Y-m-d H:i:s') . "') GROUP BY YEAR(Post.created), MONTH(Post.created)"); $expected = " WHERE ( `Post`.`created` < '" . date('Y-m-d H:i:s') . "') GROUP BY YEAR( `Post`.`created`), MONTH( `Post`.`created`)"; $this->assertEqual($result, $expected); - */ $result = $this->db->conditions('Sportstaette.sportstaette LIKE "%ru%" AND Sportstaette.sportstaettenart_id = 2'); $expected = ' WHERE `Sportstaette`.`sportstaette` LIKE "%ru%" AND `Sportstaette`.`sportstaettenart_id` = 2'; + //$this->assertPattern('/\s*WHERE\s+`Sportstaette`\.`sportstaette`\s+LIKE\s+"%ru%"\s+AND\s+`Sports/', $result); $this->assertEqual($result, $expected); $result = $this->db->conditions('Sportstaette.sportstaettenart_id = 2 AND Sportstaette.sportstaette LIKE "%ru%"'); $expected = ' WHERE `Sportstaette`.`sportstaettenart_id` = 2 AND `Sportstaette`.`sportstaette` LIKE "%ru%"'; $this->assertEqual($result, $expected); - /* $result = $this->db->conditions('SUM(Post.comments_count) > 500 AND NOT Post.title IS NULL AND NOT Post.extended_title IS NULL'); $expected = ' WHERE SUM( `Post`.`comments_count`) > 500 AND NOT `Post`.`title` IS NULL AND NOT `Post`.`extended_title` IS NULL'; $this->assertEqual($result, $expected); - */ - /* $result = $this->db->conditions('NOT Post.title IS NULL AND NOT Post.extended_title IS NULL AND SUM(Post.comments_count) > 500'); $expected = ' WHERE NOT `Post`.`title` IS NULL AND NOT `Post`.`extended_title` IS NULL AND SUM( `Post`.`comments_count`) > 500'; $this->assertEqual($result, $expected); - */ - /* $result = $this->db->conditions('NOT Post.extended_title IS NULL AND NOT Post.title IS NULL AND Post.title != "" AND SPOON(SUM(Post.comments_count) + 1.1) > 500'); $expected = ' WHERE NOT `Post`.`extended_title` IS NULL AND NOT `Post`.`title` IS NULL AND `Post`.`title` != "" AND SPOON(SUM( `Post`.`comments_count`) + 1.1) > 500'; $this->assertEqual($result, $expected); - */ $result = $this->db->conditions('NOT Post.title_extended IS NULL AND NOT Post.title IS NULL AND Post.title_extended != Post.title'); $expected = ' WHERE NOT `Post`.`title_extended` IS NULL AND NOT `Post`.`title` IS NULL AND `Post`.`title_extended` != `Post`.`title`'; @@ -774,57 +628,355 @@ class DboSourceTest extends UnitTestCase { function testArrayConditionsParsing() { $result = $this->db->conditions(array('Candy.name' => 'LIKE a', 'HardCandy.name' => 'LIKE c')); - $expected = " WHERE (`Candy`.`name` LIKE 'a') AND (`HardCandy`.`name` LIKE 'c')"; - $this->assertEqual($result, $expected); + $this->assertPattern("/^\s+WHERE\s+`Candy`.`name` LIKE\s+'a'\s+AND\s+`HardCandy`.`name`\s+LIKE\s+'c'/", $result); $result = $this->db->conditions(array('HardCandy.name' => 'LIKE a', 'Candy.name' => 'LIKE c')); - $expected = " WHERE (`HardCandy`.`name` LIKE 'a') AND (`Candy`.`name` LIKE 'c')"; + $expected = " WHERE `HardCandy`.`name` LIKE 'a' AND `Candy`.`name` LIKE 'c'"; + $this->assertEqual($result, $expected); + + $result = $this->db->conditions(array('HardCandy.name' => 'LIKE a%', 'Candy.name' => 'LIKE %c%')); + $expected = " WHERE `HardCandy`.`name` LIKE 'a%' AND `Candy`.`name` LIKE '%c%'"; + $this->assertEqual($result, $expected); + + $result = $this->db->conditions(array('HardCandy.name' => 'LIKE to be or%', 'Candy.name' => 'LIKE %not to be%')); + $expected = " WHERE `HardCandy`.`name` LIKE 'to be or%' AND `Candy`.`name` LIKE '%not to be%'"; $this->assertEqual($result, $expected); $result = $this->db->conditions(array('score' => 'BETWEEN 90.1 AND 95.7')); - $expected = " WHERE (`score` BETWEEN '90.1' AND '95.7')"; + $expected = " WHERE `score` BETWEEN '90.1' AND '95.7'"; $this->assertEqual($result, $expected); $result = $this->db->conditions(array('Post.title' => 1.1)); - $expected = " WHERE (`Post`.`title` = 1.1)"; + $expected = " WHERE `Post`.`title` = 1.1"; $this->assertEqual($result, $expected); $result = $this->db->conditions(array('SUM(Post.comments_count)' => '> 500')); - $expected = " WHERE (SUM(`Post`.`comments_count`) > 500)"; + $expected = " WHERE SUM(`Post`.`comments_count`) > 500"; + $this->assertEqual($result, $expected); + + $result = $this->db->conditions(array('MAX(Post.rating)' => '> 50')); + $expected = " WHERE MAX(`Post`.`rating`) > 50"; $this->assertEqual($result, $expected); $result = $this->db->conditions(array('title' => 'LIKE %hello')); - $expected = " WHERE (`title` LIKE '%hello')"; + $expected = " WHERE `title` LIKE '%hello'"; $this->assertEqual($result, $expected); - $result = $this->db->conditions(array('Post.name' => 'mad(g)ik')); - $expected = " WHERE (`Post`.`name` mad(g) 'ik')"; + $result = $this->db->conditions(array('Post.name' => '= mad(g)ik')); + $expected = " WHERE `Post`.`name` = 'mad(g)ik'"; + $this->assertEqual($result, $expected); + + $result = $this->db->conditions(array('score' => array(1, 2, 10))); + $expected = " WHERE `score` IN (1, 2, 10) "; + $this->assertEqual($result, $expected); + + $result = $this->db->conditions(array('score' => '!= 20')); + $expected = " WHERE `score` != 20"; + $this->assertEqual($result, $expected); + + $result = $this->db->conditions(array('score' => '> 20')); + $expected = " WHERE `score` > 20"; + $this->assertEqual($result, $expected); + + $result = $this->db->conditions(array('or' => array( 'score' => 'BETWEEN 4 AND 5', 'rating' => '> 20') )); + $expected = " WHERE (`score` BETWEEN '4' AND '5') OR (`rating` > 20)"; + $this->assertEqual($result, $expected); + + $result = $this->db->conditions(array('or' => array('score' => 'BETWEEN 4 AND 5', array('score' => '> 20')) )); + $expected = " WHERE (`score` > 20) OR (`score` BETWEEN '4' AND '5')"; + $this->assertEqual($result, $expected); + + $result = $this->db->conditions(array('and' => array( 'score' => 'BETWEEN 4 AND 5', array('score' => '> 20')) )); + $expected = " WHERE (`score` > 20) AND (`score` BETWEEN '4' AND '5')"; + $this->assertEqual($result, $expected); + + $result = $this->db->conditions(array('published' => 1, 'or' => array( 'score' => '< 2', array('score' => '> 20')) )); + $expected = " WHERE `published` = 1 AND (`score` > 20) OR (`score` < 2)"; $this->assertEqual($result, $expected); } function testFieldParsing() { - /* $result = $this->db->fields($this->model, 'Post', "CONCAT(REPEAT(' ', COUNT(Parent.name) - 1), Node.name) AS name, Node.created"); $expected = array("CONCAT(REPEAT(' ', COUNT(`Parent`.`name`) - 1), Node.name) AS name", "`Node`.`created`"); $this->assertEqual($result, $expected); - */ - /* $result = $this->db->fields($this->model, 'Post', "Node.created, CONCAT(REPEAT(' ', COUNT(Parent.name) - 1), Node.name) AS name"); $expected = array("`Node`.`created`", "CONCAT(REPEAT(' ', COUNT(`Parent`.`name`) - 1), Node.name) AS name"); $this->assertEqual($result, $expected); - */ - /* $result = $this->db->fields($this->model, 'Post', "2.2,COUNT(*), SUM(Something.else) as sum, Node.created, CONCAT(REPEAT(' ', COUNT(Parent.name) - 1), Node.name) AS name,Post.title,Post.1,1.1"); $expected = array( '2.2', 'COUNT(*)', 'SUM(`Something`.`else`) as sum', '`Node`.`created`', "CONCAT(REPEAT(' ', COUNT(`Parent`.`name`) - 1), Node.name) AS name", '`Post`.`title`', '`Post`.`1`', '1.1' ); $this->assertEqual($result, $expected); - */ + + $result = $this->db->fields($this->model, 'Post'); + $expected = array( + '`Post`.`id`', '`Post`.`client_id`', '`Post`.`name`', '`Post`.`login`', + '`Post`.`passwd`', '`Post`.`addr_1`', '`Post`.`addr_2`', '`Post`.`zip_code`', + '`Post`.`city`', '`Post`.`country`', '`Post`.`phone`', '`Post`.`fax`', + '`Post`.`url`', '`Post`.`email`', '`Post`.`comments`', '`Post`.`last_login`', + '`Post`.`created`', '`Post`.`updated`' + ); + $this->assertEqual($result, $expected); + + $result = $this->db->fields($this->model, 'Other'); + $expected = array( + '`Other`.`id`', '`Other`.`client_id`', '`Other`.`name`', '`Other`.`login`', + '`Other`.`passwd`', '`Other`.`addr_1`', '`Other`.`addr_2`', '`Other`.`zip_code`', + '`Other`.`city`', '`Other`.`country`', '`Other`.`phone`', '`Other`.`fax`', + '`Other`.`url`', '`Other`.`email`', '`Other`.`comments`', '`Other`.`last_login`', + '`Other`.`created`', '`Other`.`updated`' + ); + $this->assertEqual($result, $expected); + + $result = $this->db->fields($this->model, null, array(), false); + $expected = array('id', 'client_id', 'name', 'login', 'passwd', 'addr_1', 'addr_2', 'zip_code', 'city', 'country', 'phone', 'fax', 'url', 'email', 'comments', 'last_login', 'created', 'updated'); + $this->assertEqual($result, $expected); } + function testMergeAssociations() { + $data = array( + 'Article' => array( + 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' + ) + ); + $merge = array( + 'Topic' => array ( + array( + 'id' => '1', 'topic' => 'Topic', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ) + ) + ); + $expected = array( + 'Article' => array( + 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' + ), + 'Topic' => array( + 'id' => '1', 'topic' => 'Topic', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ) + ); + $this->db->__mergeAssociation($data, $merge, 'Topic', 'hasOne'); + $this->assertEqual($data, $expected); + + $data = array( + 'Article' => array( + 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' + ) + ); + $merge = array( + 'User' => array ( + array( + 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ) + ) + ); + $expected = array( + 'Article' => array( + 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' + ), + 'User' => array( + 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ) + ); + $this->db->__mergeAssociation($data, $merge, 'User', 'belongsTo'); + $this->assertEqual($data, $expected); + + $data = array( + 'Article' => array( + 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' + ) + ); + $merge = array( + array ( + 'Comment' => false + ) + ); + $expected = array( + 'Article' => array( + 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' + ), + 'Comment' => array() + ); + $this->db->__mergeAssociation($data, $merge, 'Comment', 'hasMany'); + $this->assertEqual($data, $expected); + + $data = array( + 'Article' => array( + 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' + ) + ); + $merge = array( + array ( + 'Comment' => array( + 'id' => '1', 'comment' => 'Comment 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ) + ), + array( + 'Comment' => array( + 'id' => '2', 'comment' => 'Comment 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ) + ) + ); + $expected = array( + 'Article' => array( + 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' + ), + 'Comment' => array( + array( + 'id' => '1', 'comment' => 'Comment 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ), + array( + 'id' => '2', 'comment' => 'Comment 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ) + ) + ); + $this->db->__mergeAssociation($data, $merge, 'Comment', 'hasMany'); + $this->assertEqual($data, $expected); + + $data = array( + 'Article' => array( + 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' + ) + ); + $merge = array( + array ( + 'Comment' => array( + 'id' => '1', 'comment' => 'Comment 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ), + 'User' => array( + 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ) + ), + array( + 'Comment' => array( + 'id' => '2', 'comment' => 'Comment 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ), + 'User' => array( + 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ) + ) + ); + $expected = array( + 'Article' => array( + 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' + ), + 'Comment' => array( + array( + 'id' => '1', 'comment' => 'Comment 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', + 'User' => array( + 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ) + ), + array( + 'id' => '2', 'comment' => 'Comment 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', + 'User' => array( + 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ) + ) + ) + ); + $this->db->__mergeAssociation($data, $merge, 'Comment', 'hasMany'); + $this->assertEqual($data, $expected); + + $data = array( + 'Article' => array( + 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' + ) + ); + $merge = array( + array ( + 'Comment' => array( + 'id' => '1', 'comment' => 'Comment 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ), + 'User' => array( + 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ), + 'Tag' => array( + array('id' => 1, 'tag' => 'Tag 1'), + array('id' => 2, 'tag' => 'Tag 2') + ) + ), + array( + 'Comment' => array( + 'id' => '2', 'comment' => 'Comment 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ), + 'User' => array( + 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ), + 'Tag' => array() + ) + ); + $expected = array( + 'Article' => array( + 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' + ), + 'Comment' => array( + array( + 'id' => '1', 'comment' => 'Comment 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', + 'User' => array( + 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ), + 'Tag' => array( + array('id' => 1, 'tag' => 'Tag 1'), + array('id' => 2, 'tag' => 'Tag 2') + ) + ), + array( + 'id' => '2', 'comment' => 'Comment 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', + 'User' => array( + 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ), + 'Tag' => array() + ) + ) + ); + $this->db->__mergeAssociation($data, $merge, 'Comment', 'hasMany'); + $this->assertEqual($data, $expected); + + $data = array( + 'Article' => array( + 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' + ) + ); + $merge = array( + array ( + 'Tag' => array( + 'id' => '1', 'tag' => 'Tag 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ) + ), + array( + 'Tag' => array( + 'id' => '2', 'tag' => 'Tag 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ) + ), + array( + 'Tag' => array( + 'id' => '3', 'tag' => 'Tag 3', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ) + ) + ); + $expected = array( + 'Article' => array( + 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' + ), + 'Tag' => array( + array( + 'id' => '1', 'tag' => 'Tag 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ), + array( + 'id' => '2', 'tag' => 'Tag 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ), + array( + 'id' => '3', 'tag' => 'Tag 3', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' + ) + ) + ); + $this->db->__mergeAssociation($data, $merge, 'Tag', 'hasAndBelongsToMany'); + $this->assertEqual($data, $expected); + } + function testMagicMethodQuerying() { $result = $this->db->query('findByFieldName', array('value'), $this->model); $expected = array('TestModel.field_name' => '= value'); @@ -854,28 +1006,6 @@ class DboSourceTest extends UnitTestCase { $expected = " ORDER BY ADDTIME(`Event`.`time_begin`, '-06:00:00') ASC"; $this->assertEqual($result, $expected); } - - function testSomething() { - $this->model->Test2 = new TestModel2(); - $this->model->hasAndBelongsToMany = array('Test2' => array( - // 'with' => 'Testship', - 'className' => 'TestModel2', - 'joinTable' => 'tests', - 'foreignKey' => 'contact_id', - 'associationForeignKey' => 'project_id', - 'conditions' => null, - 'fields' => null, - 'order' => null, - 'limit' => null, - 'offset' => null, - 'unique' => null, - 'finderQuery' => null, - 'deleteQuery' => null, - 'insertQuery' => null - )); - - //generateAssociationQuery($this->model, $this->model->Test2, $type, $association = null, $assocData = array(), &$queryData, $external = false, &$resultSet) - } } ?> \ No newline at end of file diff --git a/cake/tests/cases/libs/model/model.test.php b/cake/tests/cases/libs/model/model.test.php index dff160e38..5c9c84251 100644 --- a/cake/tests/cases/libs/model/model.test.php +++ b/cake/tests/cases/libs/model/model.test.php @@ -645,9 +645,6 @@ class ModelTest extends UnitTestCase { ); $this->assertEqual($result, $expected); - $db =& ConnectionManager::getDataSource('test_suite'); - $db->fullDebug = true; - $this->model->recursive = 2; $result = $this->model->read('id, user', 3); $expected = array( @@ -707,7 +704,9 @@ class ModelTest extends UnitTestCase { ) ); $this->assertEqual($result, $expected); - + + $this->db->fullDebug = true; + $result = $this->model->findAll(array('Article.user_id' => 3), null, null, null, 1, 2); $expected = array ( array ( @@ -747,7 +746,12 @@ class ModelTest extends UnitTestCase { ) ) ); - $this->assertEqual($result, $expected); + /*pr($result); + pr($expected); + pr(var_dump($expected[0]['Comment'][0]['Attachment'])); + pr(var_dump($result[0]['Comment'][0]['Attachment'])); + pr(array_diff_recursive($result, $expected));*/ + $this->assertEqual($expected, $result); } function testSaveField() { diff --git a/cake/tests/groups/no_database.group.php b/cake/tests/groups/no_database.group.php index 0e48d7b06..8d4cae31f 100644 --- a/cake/tests/groups/no_database.group.php +++ b/cake/tests/groups/no_database.group.php @@ -43,7 +43,6 @@ class AllCoreWithOutDatabaseGroupTest extends GroupTest { TestManager::addTestFile($this, CORE_TEST_CASES . DS . 'libs' . DS . 'validation'); TestManager::addTestFile($this, CORE_TEST_CASES . DS . 'libs' . DS . 'session'); TestManager::addTestFile($this, CORE_TEST_CASES . DS . 'libs' . DS . 'socket'); - TestManager::addTestFile($this, CORE_TEST_CASES . DS . 'libs' . DS . 'model' . DS . 'model'); TestManager::addTestCasesFromDirectory($this, CORE_TEST_CASES . DS . 'libs' . DS . 'view'); } }