Commit cfc7d4e4 authored by romanb's avatar romanb

Refactoring. Started to introduced a clear separation between column names and...

Refactoring. Started to introduced a clear separation between column names and field names (aka column aliases).\nDoctrine_Connection, DQL Parser classes/methods map field names => column names.\nDoctrine_Hydrate maps column names => field names during hydration.\nColumn names are only stored in Doctrine_Table:: and Doctrine_Table::.\nRelations use column names in 'local'/'foreign'.\nWhen using field names (column aliases) you need to use the column names in 'local'/'foreign' when setting up a relation (hasOne/hasMany), not the field names.\n\n In other words column names are only used to communicate with the database. field names are used everywhere else. the casing of field names does not matter. column names are forced to lower case for portability. If you dont use field names (column aliases) your column names are your field names (and therefore all lowercase).
parent 95792cdb
Beta 2
------
* r3183: NestedSet: 'level' column renamed to 'lvl' because LEVEL is an oracle keyword.
In order to upgrade existing trees you need to rename the level column to lvl
in your databases. This does not affect your code because the NestedSet now uses
a column alias (lvl as level). So your code still refers to the 'level' field.
* r3048: Doctrine::exportSchema() replaced by Doctrine::createTablesFromModels()
* r3048: Doctrine::exportSql() replaced by Doctrine::generateSqlFromModels()
* r3048: Doctrine::importSchema() replaced by Doctrine::generateModelsFromDb()
......
......@@ -151,7 +151,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
protected $options = array();
/**
* @var array $availableDrivers an array containing all availible drivers
* @var array $availableDrivers an array containing all available drivers
*/
private static $availableDrivers = array(
'Mysql',
......@@ -180,7 +180,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
$this->isConnected = true;
} elseif (is_array($adapter)) {
} else if (is_array($adapter)) {
$this->pendingAttributes[Doctrine::ATTR_DRIVER_NAME] = $adapter['scheme'];
$this->options['dsn'] = $adapter['dsn'];
......@@ -468,7 +468,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
* @throws PDOException if something fails at PDO level
* @return integer number of rows affected
*/
public function replace($table, array $fields, array $keys)
public function replace(Doctrine_Table $table, array $fields, array $keys)
{
//if ( ! $this->supports('replace'))
// throw new Doctrine_Connection_Exception('replace query is not supported');
......@@ -478,26 +478,26 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
}
$condition = $values = array();
foreach ($fields as $name => $value) {
$values[$name] = $value;
foreach ($fields as $fieldName => $value) {
$values[$fieldName] = $value;
if (in_array($name, $keys)) {
if (in_array($fieldName, $keys)) {
if ($value === null)
throw new Doctrine_Connection_Exception('key value '.$name.' may not be null');
throw new Doctrine_Connection_Exception('key value '.$fieldName.' may not be null');
$condition[] = $name . ' = ?';
$condition[] = $table->getColumnName($fieldName) . ' = ?';
$conditionValues[] = $value;
}
}
$query = 'DELETE FROM ' . $this->quoteIdentifier($table) . ' WHERE ' . implode(' AND ', $condition);
$affectedRows = $this->exec($query);
$query = 'DELETE FROM ' . $this->quoteIdentifier($table->getTableName())
. ' WHERE ' . implode(' AND ', $condition);
$affectedRows = $this->exec($query, $conditionValues);
$this->insert($table, $values);
$affectedRows++;
return $affectedRows;
}
......@@ -509,16 +509,16 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
* @param array $identifier An associateve array containing identifier column-value pairs.
* @return integer The number of affected rows
*/
public function delete($table, array $identifier)
public function delete(Doctrine_Table $table, array $identifier)
{
$tmp = array();
foreach (array_keys($identifier) as $id) {
$tmp[] = $id . ' = ?';
$tmp[] = $table->getColumnName($id) . ' = ?';
}
$query = 'DELETE FROM '
. $this->quoteIdentifier($table)
. $this->quoteIdentifier($table->getTableName())
. ' WHERE ' . implode(' AND ', $tmp);
......@@ -534,27 +534,27 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
* @return mixed boolean false if empty value array was given,
* otherwise returns the number of affected rows
*/
public function update($table, array $values, array $identifier)
public function update(Doctrine_Table $table, array $fields, array $identifier)
{
if (empty($values)) {
if (empty($fields)) {
return false;
}
$set = array();
foreach ($values as $name => $value) {
foreach ($fields as $fieldName => $value) {
if ($value instanceof Doctrine_Expression) {
$set[] = $name . ' = ' . $value->getSql();
$set[] = $table->getColumnName($fieldName) . ' = ' . $value->getSql();
unset($values[$name]);
} else {
$set[] = $name . ' = ?';
$set[] = $table->getColumnName($fieldName) . ' = ?';
}
}
$params = array_merge(array_values($values), array_values($identifier));
$params = array_merge(array_values($fields), array_values($identifier));
$sql = 'UPDATE ' . $this->quoteIdentifier($table)
$sql = 'UPDATE ' . $this->quoteIdentifier($table->getTableName())
. ' SET ' . implode(', ', $set)
. ' WHERE ' . implode(' = ? AND ', array_keys($identifier))
. ' WHERE ' . implode(' = ? AND ', $table->getIdentifierColumnNames())
. ' = ?';
return $this->exec($sql, $params);
......@@ -568,34 +568,36 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
* @return mixed boolean false if empty value array was given,
* otherwise returns the number of affected rows
*/
public function insert($table, array $values) {
if (empty($values)) {
public function insert(Doctrine_Table $table, array $fields) {
if (empty($fields)) {
return false;
}
$tableName = $table->getTableName();
// column names are specified as array keys
$cols = array();
// the query VALUES will contain either expresions (eg 'NOW()') or ?
$a = array();
foreach ($values as $k => $value) {
$cols[] = $this->quoteIdentifier($k);
foreach ($fields as $fieldName => $value) {
$cols[] = $this->quoteIdentifier($table->getColumnName($fieldName));
if ($value instanceof Doctrine_Expression) {
$a[] = $value->getSql();
unset($values[$k]);
unset($fields[$fieldName]);
} else {
$a[] = '?';
}
}
// build the statement
$query = 'INSERT INTO ' . $this->quoteIdentifier($table)
$query = 'INSERT INTO ' . $this->quoteIdentifier($tableName)
. ' (' . implode(', ', $cols) . ') '
. 'VALUES (';
$query .= implode(', ', $a) . ')';
// prepare and execute the statement
return $this->exec($query, array_values($values));
return $this->exec($query, array_values($fields));
}
/**
......@@ -912,6 +914,7 @@ abstract class Doctrine_Connection extends Doctrine_Configurable implements Coun
$this->getAttribute(Doctrine::ATTR_LISTENER)->preQuery($event);
if ( ! $event->skipOperation) {
//echo $query . "<br />";
$stmt = $this->dbh->query($query);
$this->_count++;
......
......@@ -166,7 +166,7 @@ class Doctrine_Connection_Mysql extends Doctrine_Connection_Common
*
* @return integer the number of affected rows
*/
public function replace($table, array $fields, array $keys)
public function replace(Doctrine_Table $table, array $fields, array $keys)
{
$count = count($fields);
$query = $values = '';
......@@ -180,7 +180,7 @@ class Doctrine_Connection_Mysql extends Doctrine_Connection_Common
$values.= ',';
}
$query .= $name;
$query .= $table->getColumnName($name);
if (isset($fields[$name]['null']) && $fields[$name]['null']) {
$value = 'NULL';
......@@ -202,7 +202,7 @@ class Doctrine_Connection_Mysql extends Doctrine_Connection_Common
if ($keys == 0) {
throw new Doctrine_Connection_Mysql_Exception('not specified which fields are keys');
}
$query = 'REPLACE INTO ' . $table . ' (' . $query . ') VALUES (' . $values . ')';
$query = 'REPLACE INTO ' . $table->getTableName() . ' (' . $query . ') VALUES (' . $values . ')';
return $this->exec($query);
}
......
......@@ -148,9 +148,8 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
}
$record->state(Doctrine_Record::STATE_LOCKED);
$conn->beginTransaction();
$saveLater = $this->saveRelated($record);
$record->state($state);
......@@ -159,7 +158,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
$event = new Doctrine_Event($record, Doctrine_Event::RECORD_SAVE);
$record->preSave($event);
$record->getTable()->getRecordListener()->preSave($event);
$state = $record->state();
......@@ -180,7 +179,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
}
$record->getTable()->getRecordListener()->postSave($event);
$record->postSave($event);
} else {
$conn->transaction->addInvalid($record);
......@@ -195,7 +194,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
if ($record->hasReference($alias)) {
$obj = $record->$alias;
// check that the related object is not an instance of Doctrine_Null
if ( ! ($obj instanceof Doctrine_Null)) {
$obj->save($conn);
......@@ -207,7 +206,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
$this->saveAssociations($record);
$record->state($state);
$conn->commit();
return true;
......@@ -284,10 +283,10 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
foreach ($table->getOption('joinedParents') as $parent) {
$parentTable = $table->getConnection()->getTable($parent);
$this->conn->delete($parentTable->getTableName(), $record->identifier());
$this->conn->delete($parentTable, $record->identifier());
}
}
$this->conn->delete($table->getTableName(), $record->identifier());
$this->conn->delete($table, $record->identifier());
$record->state(Doctrine_Record::STATE_TCLEAN);
} else {
......@@ -295,7 +294,6 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
$record->state($state);
}
$table->getRecordListener()->postDelete($event);
$record->postDelete($event);
......@@ -554,12 +552,12 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
foreach ($classes as $class) {
$parentTable = $this->conn->getTable($class);
$this->conn->update($this->conn->getTable($class)->getTableName(), $dataSet[$class], $identifier);
$this->conn->update($this->conn->getTable($class), $dataSet[$class], $identifier);
}
} else {
$array = $record->getPrepared();
$this->conn->update($table->getTableName(), $array, $identifier);
$this->conn->update($table, $array, $identifier);
}
$record->assignIdentifier(true);
}
......@@ -608,7 +606,7 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
$dataSet[$parent][$id] = $value;
}
$this->conn->insert($this->conn->getTable($parent)->getTableName(), $dataSet[$parent]);
$this->conn->insert($this->conn->getTable($parent), $dataSet[$parent]);
}
}
} else {
......@@ -624,6 +622,10 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
return true;
}
/**
* @todo DESCRIBE WHAT THIS METHOD DOES, PLEASE!
*/
public function formatDataSet(Doctrine_Record $record)
{
$table = $record->getTable();
......@@ -634,47 +636,53 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module
$array = $record->getPrepared();
foreach ($table->getColumns() as $column => $definition) {
foreach ($table->getColumns() as $columnName => $definition) {
$fieldName = $table->getFieldName($columnName);
if (isset($definition['primary']) && $definition['primary']) {
continue;
}
if (isset($definition['owner'])) {
$dataSet[$definition['owner']][$column] = $array[$column];
$dataSet[$definition['owner']][$fieldName] = $array[$fieldName];
} else {
$dataSet[$component][$column] = $array[$column];
$dataSet[$component][$fieldName] = $array[$fieldName];
}
}
return $dataSet;
}
/**
* @todo DESCRIBE WHAT THIS METHOD DOES, PLEASE!
*/
public function processSingleInsert(Doctrine_Record $record)
{
$array = $record->getPrepared();
$fields = $record->getPrepared();
if (empty($array)) {
if (empty($fields)) {
return false;
}
$table = $record->getTable();
$keys = (array) $table->getIdentifier();
$table = $record->getTable();
$identifier = (array) $table->getIdentifier();
$seq = $record->getTable()->sequenceName;
$seq = $record->getTable()->sequenceName;
if ( ! empty($seq)) {
$id = $this->conn->sequence->nextId($seq);
$name = $record->getTable()->getIdentifier();
$array[$name] = $id;
$id = $this->conn->sequence->nextId($seq);
$seqName = $table->getIdentifier();
$fields[$seqName] = $id;
$record->assignIdentifier($id);
}
$this->conn->insert($table->getTableName(), $array);
$this->conn->insert($table, $fields);
if (empty($seq) && count($keys) == 1 && $keys[0] == $table->getIdentifier() &&
if (empty($seq) && count($identifier) == 1 && $identifier[0] == $table->getIdentifier() &&
$table->getIdentifierType() != Doctrine::IDENTIFIER_NATURAL) {
if (strtolower($this->conn->getName()) == 'pgsql') {
$seq = $table->getTableName() . '_' . $keys[0];
$seq = $table->getTableName() . '_' . $identifier[0];
}
$id = $this->conn->sequence->lastInsertId($seq);
......
......@@ -819,7 +819,7 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
if ($this->type !== self::SELECT) {
return $this->_conn->exec($query, $params);
}
//echo $query . "<br /><br />";
$stmt = $this->_conn->execute($query, $params);
return $stmt;
}
......@@ -850,7 +850,7 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
if ($cached === false) {
// cache miss
$stmt = $this->_execute($params);
$array = $this->parseData2($stmt, Doctrine::HYDRATE_ARRAY);
$array = $this->hydrateResultSet($stmt, Doctrine::HYDRATE_ARRAY);
$cached = $this->getCachedForm($array);
......@@ -883,7 +883,7 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
return $stmt;
}
$array = $this->parseData2($stmt, $hydrationMode);
$array = $this->hydrateResultSet($stmt, $hydrationMode);
}
return $array;
}
......@@ -1022,7 +1022,7 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
* @param mixed $stmt
* @return array
*/
public function parseData2($stmt, $hydrationMode)
public function hydrateResultSet($stmt, $hydrationMode)
{
if ($hydrationMode == Doctrine::HYDRATE_NONE) {
return $stmt->fetchAll(PDO::FETCH_NUM);
......@@ -1076,29 +1076,33 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
// of magnitude.
if ( ! isset($cache[$key])) {
$e = explode('__', $key);
$cache[$key]['field'] = $field = strtolower(array_pop($e));
$last = strtolower(array_pop($e));
$cache[$key]['alias'] = $this->_tableAliases[strtolower(implode('__', $e))];
$fieldName = $this->_aliasMap[$cache[$key]['alias']]['table']->getFieldName($last);
//echo "hydrate:" . $fieldName . "<br /><br />";
$cache[$key]['fieldName'] = $fieldName;
$cache[$key]['columnName'] = $last;
}
$map = $this->_aliasMap[$cache[$key]['alias']];
$table = $map['table'];
$alias = $cache[$key]['alias'];
$field = $cache[$key]['field'];
$fieldName = $cache[$key]['fieldName'];
if (isset($this->_aliasMap[$alias]['agg'][$field])) {
$field = $this->_aliasMap[$alias]['agg'][$field];
if (isset($this->_aliasMap[$alias]['agg'][$fieldName])) {
$fieldName = $this->_aliasMap[$alias]['agg'][$fieldName];
}
if ($table->isIdentifier($field)) {
if ($table->isIdentifier($fieldName)) {
$id[$alias] .= '|' . $value;
}
$currData[$alias][$field] = $table->prepareValue($field, $value);
$currData[$alias][$fieldName] = $table->prepareValue($fieldName, $value);
if ($value !== null) {
$identifiable[$alias] = true;
}
}
// dealing with root component
......@@ -1162,7 +1166,7 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
if ( ! isset($prev[$parent])) {
break;
}
// check the type of the relation
if ( ! $relation->isOneToOne()) {
// initialize the collection
......@@ -1207,7 +1211,7 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
} else {
$prev[$parent][$componentAlias] = $element;
}
$oneToOne = true;
$oneToOne = true;
}
$coll =& $prev[$parent][$componentAlias];
$this->_setLastElement($prev, $coll, $index, $alias, $oneToOne);
......@@ -1215,7 +1219,7 @@ class Doctrine_Hydrate extends Doctrine_Locator_Injectable implements Serializab
}
$id[$rootAlias] = '';
}
$driver->flush();
$stmt->closeCursor();
......
......@@ -78,7 +78,7 @@ class Doctrine_Hydrate_Record extends Doctrine_Locator_Injectable
*/
public function isIdentifiable(array $row, Doctrine_Table $table)
{
$primaryKeys = $table->getIdentifier();
$primaryKeys = $table->getIdentifierColumnNames();
if (is_array($primaryKeys)) {
foreach ($primaryKeys as $id) {
......@@ -103,8 +103,15 @@ class Doctrine_Hydrate_Record extends Doctrine_Locator_Injectable
$this->_tables[$component] = Doctrine_Manager::getInstance()->getTable($component);
$this->_tables[$component]->setAttribute(Doctrine::ATTR_LOAD_REFERENCES, false);
}
//echo "..before..";
//Doctrine::dump($data);
$this->_tables[$component]->setData($data);
$record = $this->_tables[$component]->getRecord();
//echo "..after..";
//Doctrine::dump($record->getData());
if ( ! isset($this->_records[$record->getOid()]) ) {
$record->clearRelated();
......
......@@ -32,6 +32,7 @@ Doctrine::autoload('Doctrine_Query_Abstract');
*/
class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
{
/** @todo document the query states (and the transitions between them). */
const STATE_CLEAN = 1;
const STATE_DIRTY = 2;
......@@ -156,7 +157,10 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
protected $_pendingJoinConditions = array();
protected $_expressionMap = array();
/**
* @var integer $_state The current state of this query.
*/
protected $_state = Doctrine_Query::STATE_CLEAN;
/**
......@@ -170,7 +174,10 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
{
return new Doctrine_Query($conn);
}
/**
* Resets the query to the state just after it has been instantiated.
*/
public function reset()
{
$this->_pendingJoinConditions = array();
......@@ -318,6 +325,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
*
* @throws Doctrine_Query_Exception if unknown parser name given
* @return Doctrine_Query_Part
* @todo Doc/Description: What is the parameter for? Which parsers are available?
*/
public function getParser($name)
{
......@@ -386,10 +394,12 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
/**
* getDqlPart
* returns the given DQL query part
* returns a specific DQL query part.
*
* @param string $queryPart the name of the query part
* @return string the DQL query part
* @todo Description: List which query parts exist or point to the method/property
* where they are listed.
*/
public function getDqlPart($queryPart)
{
......@@ -402,7 +412,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
/**
* getDql
* returns the DQL query associated with this object
* returns the DQL query that is represented by this query object.
*
* the query is built from $_dqlParts
*
......@@ -432,6 +442,8 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
* @throws Doctrine_Query_Exception if unknown component alias has been given
* @param string $componentAlias the alias of the component
* @return void
* @todo Description: What is a 'pending field' (and are there non-pending fields, too)?
* What is 'processed'? (Meaning: What information is gathered & stored away)
*/
public function processPendingFields($componentAlias)
{
......@@ -443,6 +455,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
// check for wildcards
if (in_array('*', $fields)) {
//echo "<br />";Doctrine::dump($table->getColumnNames()); echo "<br />";
$fields = $table->getColumnNames();
} else {
// only auto-add the primary key fields if this query object is not
......@@ -477,7 +490,8 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
}
$this->_neededTables[] = $tableAlias;
//Doctrine::dump(implode(', ', $sql));
//echo "<br /><br />";
return implode(', ', $sql);
}
}
......@@ -487,6 +501,9 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
*
* @throws Doctrine_Query_Exception if unknown component alias has been given
* @return void
* @todo Description: Explain what this method does. Is there a relation to parseSelect()?
* (It doesnt seem to get called from there...?). In what circumstances is this method
* used?
*/
public function parseSelectField($field)
{
......@@ -533,6 +550,8 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
*
* @param string $expr expression from which to get to owner from
* @return string the component alias
* @todo Description: What does it mean if a component is an 'owner' of an expression?
* What kind of 'expression' are we talking about here?
*/
public function getExpressionOwner($expr)
{
......@@ -557,6 +576,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
* adds selected fields to pendingFields array
*
* @param string $dql
* @todo Description: What information is extracted (and then stored)?
*/
public function parseSelect($dql)
{
......@@ -640,8 +660,10 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
* 5. Parses nested clauses and subqueries recursively
*
* @return string SQL string
* @todo Description: What is a 'dql clause' (and what not)?
* Refactor: Too long & nesting level
*/
public function parseClause($clause)
public function parseClause($clause)
{
$clause = trim($clause);
......@@ -670,7 +692,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
// convert DQL function to its RDBMS specific equivalent
try {
$expr = call_user_func_array(array($this->_conn->expression, $name), $args);
} catch(Doctrine_Expression_Exception $e) {
} catch (Doctrine_Expression_Exception $e) {
throw new Doctrine_Query_Exception('Unknown function ' . $expr . '.');
}
$term[0] = $expr;
......@@ -849,6 +871,8 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
* since some subqueries may be correlated
*
* @return void
* @todo Better description. i.e. What is a 'pending subquery'? What does 'processed' mean?
* (parsed? sql is constructed? some information is gathered?)
*/
public function processPendingSubqueries()
{
......@@ -878,6 +902,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
* processes pending aggregate values for given component alias
*
* @return void
* @todo Better description. i.e. What is a 'pending aggregate'? What does 'processed' mean?
*/
public function processPendingAggregates()
{
......@@ -1135,7 +1160,8 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
$table = $map['table'];
$rootAlias = key($this->_aliasMap);
if ( ! empty($this->parts['limit']) && $this->needsSubquery && $table->getAttribute(Doctrine::ATTR_QUERY_LIMIT) == Doctrine::LIMIT_RECORDS) {
if ( ! empty($this->parts['limit']) && $this->needsSubquery &&
$table->getAttribute(Doctrine::ATTR_QUERY_LIMIT) == Doctrine::LIMIT_RECORDS) {
$this->isLimitSubqueryUsed = true;
$needsSubQuery = true;
}
......@@ -1235,6 +1261,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
* of limiting the number of sql result set rows
*
* @return string the limit subquery
* @todo A little refactor to make the method easier to understand & maybe shorter?
*/
public function getLimitSubquery()
{
......@@ -1445,7 +1472,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
$parts = $this->tokenizeQuery($query);
foreach($parts as $k => $part) {
foreach ($parts as $k => $part) {
$part = implode(' ', $part);
$k = strtolower($k);
switch ($k) {
......@@ -1485,7 +1512,10 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
return $this;
}
/**
* @todo DESCRIBE ME! REFACTOR ME! I'M FAR TOO LONG AND COMPLEX! HARD TO UNDERSTAND!
*/
public function load($path, $loadFields = true)
{
if (isset($this->_aliasMap[$path])) {
......@@ -1610,7 +1640,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
$queryPart .= ' ON ' . $localAlias
. '.'
. $localTable->getIdentifier()
. $localTable->getIdentifier() // what about composite keys?
. ' = '
. $assocAlias . '.' . $relation->getLocal();
......@@ -1708,6 +1738,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
*
* @param string $name
* @param string $componentAlias
* @todo DESCRIBE ME!
*/
public function loadRoot($name, $componentAlias)
{
......@@ -1737,11 +1768,14 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
return $table;
}
/**
* @todo DESCRIBE ME!
*/
public function buildInheritanceJoinSql($name, $componentAlias)
{
// get the connection for the component
$this->_conn = Doctrine_Manager::getInstance()
->getConnectionForComponent($name);
$this->_conn = Doctrine_Manager::getInstance()->getConnectionForComponent($name);
$table = $this->_conn->getTable($name);
$tableName = $table->getTableName();
......@@ -1762,6 +1796,7 @@ class Doctrine_Query extends Doctrine_Query_Abstract implements Countable
$queryPart .= ' LEFT JOIN ' . $this->_conn->quoteIdentifier($parentTable->getTableName())
. ' ' . $this->_conn->quoteIdentifier($parentTableAlias) . ' ON ';
//Doctrine::dump($table->getIdentifier());
foreach ((array) $table->getIdentifier() as $identifier) {
$column = $table->getColumnName($identifier);
......
......@@ -105,7 +105,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
protected $_state;
/**
* @var array $_modified an array containing properties that have been modified
* @var array $_modified an array containing field names that have been modified
*/
protected $_modified = array();
......@@ -156,48 +156,47 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
// Check if the current connection has the records table in its registry
// If not this record is only used for creating table definition and setting up
// relations.
if ( ! $this->_table->getConnection()->hasTable($this->_table->getComponentName())) {
return;
}
if ($this->_table->getConnection()->hasTable($this->_table->getComponentName())) {
$this->_oid = self::$_index;
self::$_index++;
$keys = (array) $this->_table->getIdentifier();
$this->_oid = self::$_index;
// get the data array
$this->_data = $this->_table->getData();
self::$_index++;
// get the column count
$count = count($this->_data);
// get the data array
$this->_data = $this->_table->getData();
$this->_values = $this->cleanData($this->_data);
// get the column count
$count = count($this->_data);
$this->prepareIdentifiers($exists);
$this->_values = $this->cleanData($this->_data);
if ( ! $exists) {
if ($count > count($this->_values)) {
$this->_state = Doctrine_Record::STATE_TDIRTY;
} else {
$this->_state = Doctrine_Record::STATE_TCLEAN;
}
$this->prepareIdentifiers($exists);
// set the default values for this record
$this->assignDefaultValues();
if ( ! $exists) {
if ($count > count($this->_values)) {
$this->_state = Doctrine_Record::STATE_TDIRTY;
} else {
$this->_state = Doctrine_Record::STATE_CLEAN;
if ($count < $this->_table->getColumnCount()) {
$this->_state = Doctrine_Record::STATE_PROXY;
}
$this->_state = Doctrine_Record::STATE_TCLEAN;
}
$this->_errorStack = new Doctrine_Validator_ErrorStack(get_class($this));
// set the default values for this record
$this->assignDefaultValues();
} else {
$this->_state = Doctrine_Record::STATE_CLEAN;
$repository = $this->_table->getRepository();
$repository->add($this);
$this->construct();
if ($count < $this->_table->getColumnCount()) {
$this->_state = Doctrine_Record::STATE_PROXY;
}
}
$this->_errorStack = new Doctrine_Validator_ErrorStack(get_class($this));
$repository = $this->_table->getRepository();
$repository->add($this);
$this->construct();
}
......@@ -434,13 +433,14 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
$tmp = $data;
$data = array();
foreach ($this->getTable()->getColumnNames() as $name) {
if ( ! isset($tmp[$name])) {
$data[$name] = self::$_null;
//Doctrine::dump($this->getTable()->getFieldNames());
foreach ($this->getTable()->getFieldNames() as $fieldName) {
if ( ! isset($tmp[$fieldName])) {
$data[$fieldName] = self::$_null;
} else {
$data[$name] = $tmp[$name];
$data[$fieldName] = $tmp[$fieldName];
}
unset($tmp[$name]);
unset($tmp[$fieldName]);
}
return $tmp;
......@@ -455,9 +455,10 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
*/
public function hydrate(array $data)
{
$this->_values = array_merge($this->_values, $this->cleanData($data));
$this->_data = array_merge($this->_data, $data);
//Doctrine::dump($this->_data);
$this->prepareIdentifiers(true);
}
......@@ -475,7 +476,9 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
case Doctrine::IDENTIFIER_SEQUENCE:
case Doctrine::IDENTIFIER_NATURAL:
$name = $this->_table->getIdentifier();
if (is_array($name)) {
$name = $name[0];
}
if ($exists) {
if (isset($this->_data[$name]) && $this->_data[$name] !== self::$_null) {
$this->_id[$name] = $this->_data[$name];
......@@ -623,7 +626,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
} else {
$err = true;
}
} elseif (is_string($state)) {
} else if (is_string($state)) {
$upper = strtoupper($state);
$const = 'Doctrine_Record::STATE_' . $upper;
......@@ -677,7 +680,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
$this->prepareIdentifiers();
$this->_state = Doctrine_Record::STATE_CLEAN;
$this->_state = Doctrine_Record::STATE_CLEAN;
return $this;
}
......@@ -745,15 +748,16 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
* @throws Doctrine_Record_Exception if trying to get an unknown property
* @return mixed
*/
public function rawGet($name)
public function rawGet($fieldName)
{
if ( ! isset($this->_data[$name])) {
throw new Doctrine_Record_Exception('Unknown property '. $name);
if ( ! isset($this->_data[$fieldName])) {
throw new Doctrine_Record_Exception('Unknown property '. $fieldName);
}
if ($this->_data[$name] === self::$_null)
if ($this->_data[$fieldName] === self::$_null) {
return null;
}
return $this->_data[$name];
return $this->_data[$fieldName];
}
/**
......@@ -767,9 +771,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
// only load the data from database if the Doctrine_Record is in proxy state
if ($this->_state == Doctrine_Record::STATE_PROXY) {
$this->refresh();
$this->_state = Doctrine_Record::STATE_CLEAN;
return true;
}
return false;
......@@ -784,45 +786,40 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
* @throws Doctrine_Record_Exception if trying to get a value of unknown property / related component
* @return mixed
*/
public function get($name, $load = true)
public function get($fieldName, $load = true)
{
$value = self::$_null;
$lower = strtolower($name);
$lower = $this->_table->getColumnName($lower);
if (isset($this->_data[$lower])) {
if (isset($this->_data[$fieldName])) {
// check if the property is null (= it is the Doctrine_Null object located in self::$_null)
if ($this->_data[$lower] === self::$_null && $load) {
if ($this->_data[$fieldName] === self::$_null && $load) {
$this->load();
}
if ($this->_data[$lower] === self::$_null) {
if ($this->_data[$fieldName] === self::$_null) {
$value = null;
} else {
$value = $this->_data[$lower];
$value = $this->_data[$fieldName];
}
return $value;
}
if (isset($this->_values[$lower])) {
return $this->_values[$lower];
if (isset($this->_values[$fieldName])) {
return $this->_values[$fieldName];
}
try {
if ( ! isset($this->_references[$fieldName]) && $load) {
if ( ! isset($this->_references[$name]) && $load) {
$rel = $this->_table->getRelation($fieldName);
$rel = $this->_table->getRelation($name);
$this->_references[$name] = $rel->fetchRelatedFor($this);
$this->_references[$fieldName] = $rel->fetchRelatedFor($this);
}
return $this->_references[$name];
} catch(Doctrine_Table_Exception $e) {
return $this->_references[$fieldName];
} catch (Doctrine_Table_Exception $e) {
foreach ($this->_table->getFilters() as $filter) {
if (($value = $filter->filterGet($this, $name, $value)) !== null) {
if (($value = $filter->filterGet($this, $fieldName, $value)) !== null) {
return $value;
}
}
......@@ -841,7 +838,6 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
*/
public function mapValue($name, $value)
{
$name = strtolower($name);
$this->_values[$name] = $value;
}
......@@ -859,15 +855,11 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
*
* @return Doctrine_Record
*/
public function set($name, $value, $load = true)
public function set($fieldName, $value, $load = true)
{
$lower = strtolower($name);
$lower = $this->_table->getColumnName($lower);
if (isset($this->_data[$lower])) {
if (isset($this->_data[$fieldName])) {
if ($value instanceof Doctrine_Record) {
$type = $this->_table->getTypeOf($name);
$type = $this->_table->getTypeOf($fieldName);
$id = $value->getIncremented();
......@@ -877,9 +869,9 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
}
if ($load) {
$old = $this->get($lower, $load);
$old = $this->get($fieldName, $load);
} else {
$old = $this->_data[$lower];
$old = $this->_data[$fieldName];
}
if ($old !== $value) {
......@@ -887,8 +879,8 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
$value = self::$_null;
}
$this->_data[$lower] = $value;
$this->_modified[] = $lower;
$this->_data[$fieldName] = $value;
$this->_modified[] = $fieldName;
switch ($this->_state) {
case Doctrine_Record::STATE_CLEAN:
$this->_state = Doctrine_Record::STATE_DIRTY;
......@@ -900,17 +892,21 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
}
} else {
try {
$this->coreSetRelated($name, $value);
} catch(Doctrine_Table_Exception $e) {
$this->coreSetRelated($fieldName, $value);
} catch (Doctrine_Table_Exception $e) {
foreach ($this->_table->getFilters() as $filter) {
if (($value = $filter->filterSet($this, $name, $value)) !== null) {
if (($value = $filter->filterSet($this, $fieldName, $value)) !== null) {
return $value;
}
}
}
}
}
/**
* DESCRIBE WHAT THIS METHOD DOES, PLEASE!
* @todo Refactor. What about composite keys?
*/
public function coreSetRelated($name, $value)
{
$rel = $this->_table->getRelation($name);
......@@ -929,23 +925,27 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
}
} else {
if ($value !== self::$_null) {
$relatedTable = $value->getTable();
$foreignFieldName = $relatedTable->getFieldName($rel->getForeign());
$localFieldName = $this->_table->getFieldName($rel->getLocal());
// one-to-one relation found
if ( ! ($value instanceof Doctrine_Record)) {
throw new Doctrine_Record_Exception("Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Record or Doctrine_Null when setting one-to-one references.");
}
if ($rel instanceof Doctrine_Relation_LocalKey) {
$foreign = $rel->getForeign();
if ( ! empty($foreign) && $foreign != $value->getTable()->getIdentifier())
$this->set($rel->getLocal(), $value->rawGet($foreign), false);
else
$this->set($rel->getLocal(), $value, false);
if ( ! empty($foreignFieldName) && $foreignFieldName != $value->getTable()->getIdentifier()) {
$this->set($localFieldName, $value->rawGet($foreignFieldName), false);
} else {
$this->set($localFieldName, $value, false);
}
} else {
$value->set($rel->getForeign(), $this, false);
}
$value->set($foreignFieldName, $this, false);
}
}
}
} elseif ($rel instanceof Doctrine_Relation_Association) {
} else if ($rel instanceof Doctrine_Relation_Association) {
// join table relation found
if ( ! ($value instanceof Doctrine_Collection)) {
throw new Doctrine_Record_Exception("Couldn't call Doctrine::set(), second argument should be an instance of Doctrine_Collection when setting many-to-many references.");
......@@ -961,21 +961,19 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
* @param string $name
* @return boolean
*/
public function contains($name)
public function contains($fieldName)
{
$lower = strtolower($name);
if (isset($this->_data[$lower])) {
if (isset($this->_data[$fieldName])) {
return true;
}
if (isset($this->_id[$lower])) {
if (isset($this->_id[$fieldName])) {
return true;
}
if (isset($this->_values[$lower])) {
if (isset($this->_values[$fieldName])) {
return true;
}
if (isset($this->_references[$name]) &&
$this->_references[$name] !== self::$_null) {
if (isset($this->_references[$fieldName]) &&
$this->_references[$fieldName] !== self::$_null) {
return true;
}
......@@ -986,10 +984,10 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
* @param string $name
* @return void
*/
public function __unset($name)
public function __unset($fieldName)
{
if (isset($this->_data[$name])) {
$this->_data[$name] = array();
if (isset($this->_data[$fieldName])) {
$this->_data[$fieldName] = array();
}
// todo: what to do with references ?
}
......@@ -1054,12 +1052,13 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
$conn = $this->_table->getConnection();
}
return $conn->replace($this->_table->getTableName(), $this->getPrepared(), $this->_id);
return $conn->replace($this->_table, $this->getPrepared(), $this->_id);
}
/**
* returns an array of modified fields and associated values
* @return array
* @todo What about a better name? getModifiedFields?
*/
public function getModified()
{
......@@ -1071,6 +1070,9 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
return $a;
}
/**
* REDUNDANT?
*/
public function modifiedFields()
{
$a = array();
......@@ -1089,40 +1091,41 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
*
* @param array $array
* @return array
* @todo What about a little bit more expressive name? getPreparedData?
*/
public function getPrepared(array $array = array())
{
$a = array();
if (empty($array)) {
$array = $this->_modified;
$modifiedFields = $this->_modified;
}
foreach ($array as $k => $v) {
$type = $this->_table->getTypeOf($v);
foreach ($modifiedFields as $field) {
$type = $this->_table->getTypeOf($field);
if ($this->_data[$v] === self::$_null) {
$a[$v] = null;
if ($this->_data[$field] === self::$_null) {
$a[$field] = null;
continue;
}
switch ($type) {
case 'array':
case 'object':
$a[$v] = serialize($this->_data[$v]);
$a[$field] = serialize($this->_data[$field]);
break;
case 'gzip':
$a[$v] = gzcompress($this->_data[$v],5);
$a[$field] = gzcompress($this->_data[$field],5);
break;
case 'boolean':
$a[$v] = $this->getTable()->getConnection()->convertBooleans($this->_data[$v]);
$a[$field] = $this->getTable()->getConnection()->convertBooleans($this->_data[$field]);
break;
case 'enum':
$a[$v] = $this->_table->enumIndex($v, $this->_data[$v]);
$a[$field] = $this->_table->enumIndex($field, $this->_data[$field]);
break;
default:
if ($this->_data[$v] instanceof Doctrine_Record) {
$this->_data[$v] = $this->_data[$v]->getIncremented();
if ($this->_data[$field] instanceof Doctrine_Record) {
$this->_data[$field] = $this->_data[$field]->getIncremented();
}
/** TODO:
if ($this->_data[$v] === null) {
......@@ -1130,7 +1133,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
}
*/
$a[$v] = $this->_data[$v];
$a[$field] = $this->_data[$field];
}
}
$map = $this->_table->inheritanceMap;
......@@ -1255,12 +1258,12 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
* @param mixed $name name of the property or reference
* @return boolean
*/
public function hasRelation($name)
public function hasRelation($fieldName)
{
if (isset($this->_data[$name]) || isset($this->_id[$name])) {
if (isset($this->_data[$fieldName]) || isset($this->_id[$fieldName])) {
return true;
}
return $this->_table->hasRelation($name);
return $this->_table->hasRelation($fieldName);
}
/**
......@@ -1311,8 +1314,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
if ( ! ($val instanceof Doctrine_Null)) {
$ret->_modified[] = $key;
}
}
}
return $ret;
}
......@@ -1356,7 +1358,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
$this->_state = Doctrine_Record::STATE_CLEAN;
$this->_modified = array();
} else {
$name = $this->_table->getIdentifier();
$name = $this->_table->getIdentifier();
$this->_id[$name] = $id;
$this->_data[$name] = $id;
$this->_state = Doctrine_Record::STATE_CLEAN;
......@@ -1481,12 +1483,12 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
*/
public function merge(array $values)
{
foreach ($this->_table->getColumnNames() as $value) {
foreach ($this->_table->getFieldNames() as $fieldName) {
try {
if (isset($values[$value])) {
$this->set($value, $values[$value]);
if (isset($values[$fieldName])) {
$this->set($fieldName, $values[$fieldName]);
}
} catch(Doctrine_Exception $e) {
} catch (Doctrine_Exception $e) {
// silence all exceptions
}
}
......@@ -1506,12 +1508,12 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
array_shift($args);
if (isset($args[0])) {
$column = $args[0];
$args[0] = $this->get($column);
$fieldName = $args[0];
$args[0] = $this->get($fieldName);
$newvalue = call_user_func_array($callback, $args);
$this->_data[$column] = $newvalue;
$this->_data[$fieldName] = $newvalue;
}
return $this;
}
......@@ -1592,8 +1594,7 @@ abstract class Doctrine_Record extends Doctrine_Record_Abstract implements Count
$q->execute();
} elseif ($rel instanceof Doctrine_Relation_ForeignKey) {
} else if ($rel instanceof Doctrine_Relation_ForeignKey) {
$q->update($rel->getTable()->getComponentName())
->set($rel->getForeign(), '?', array(null))
->addWhere($rel->getForeign() . ' = ?', array_values($this->identifier()));
......
......@@ -29,6 +29,7 @@
* @version $Revision: 1397 $
* @link www.phpdoctrine.com
* @since 1.0
* @todo Composite key support?
*/
class Doctrine_Relation_Parser
{
......@@ -103,11 +104,12 @@ class Doctrine_Relation_Parser
unset($this->relations[$name]);
}
/* looks like old code?
$lower = strtolower($name);
if ($this->_table->hasColumn($lower)) {
throw new Doctrine_Relation_Exception("Couldn't bind relation. Column with name " . $lower . ' already exists!');
}
*/
$e = explode(' as ', $name);
$name = $e[0];
......@@ -145,6 +147,8 @@ class Doctrine_Relation_Parser
if (isset($this->_pending[$alias])) {
$def = $this->_pending[$alias];
$identifierColumnNames = $this->_table->getIdentifierColumnNames();
$idColumnName = array_pop($identifierColumnNames);
// check if reference class name exists
// if it does we are dealing with association relation
......@@ -160,7 +164,7 @@ class Doctrine_Relation_Parser
$parser->bind($this->_table->getComponentName(),
array('type' => Doctrine_Relation::ONE,
'local' => $def['local'],
'foreign' => $this->_table->getIdentifier(),
'foreign' => $idColumnName,
'localKey' => true,
));
}
......@@ -168,7 +172,7 @@ class Doctrine_Relation_Parser
if ( ! $this->hasRelation($def['refClass'])) {
$this->bind($def['refClass'], array('type' => Doctrine_Relation::MANY,
'foreign' => $def['local'],
'local' => $this->_table->getIdentifier()));
'local' => $idColumnName));
}
}
if (in_array($def['class'], $localClasses)) {
......@@ -181,7 +185,6 @@ class Doctrine_Relation_Parser
$def = $this->completeDefinition($def);
if (isset($def['localKey'])) {
$rel = new Doctrine_Relation_LocalKey($def);
} else {
$rel = new Doctrine_Relation_ForeignKey($def);
......@@ -257,7 +260,7 @@ class Doctrine_Relation_Parser
$def['class'] = $def['table']->getComponentName();
$def['refTable'] = $this->getImpl($def['refClass']);
$id = $def['refTable']->getIdentifier();
$id = $def['refTable']->getIdentifierColumnNames();
if (count($id) > 1) {
if ( ! isset($def['foreign'])) {
......@@ -304,15 +307,15 @@ class Doctrine_Relation_Parser
*/
public function getIdentifiers(Doctrine_Table $table)
{
$componentNameToLower = strtolower($table->getComponentName());
if (is_array($table->getIdentifier())) {
$columns = array();
foreach((array) $table->getIdentifier() as $identifier) {
$columns[] = strtolower($table->getComponentName())
. '_' . $table->getIdentifier();
$columns = array();
foreach ((array) $table->getIdentifierColumnNames() as $identColName) {
$columns[] = $componentNameToLower . '_' . $identColName;
}
} else {
$columns = strtolower($table->getComponentName())
. '_' . $table->getIdentifier();
$columns = $componentNameToLower . '_' . $table->getColumnName(
$table->getIdentifier());
}
return $columns;
......@@ -361,6 +364,8 @@ class Doctrine_Relation_Parser
*
* @param array $def definition array to be completed
* @return array completed definition array
* @todo Description: What does it mean to complete a definition? What is done (not how)?
* Refactor (too long & nesting level)
*/
public function completeDefinition($def)
{
......@@ -371,21 +376,26 @@ class Doctrine_Relation_Parser
$foreignClasses = array_merge($def['table']->getOption('parents'), array($def['class']));
$localClasses = array_merge($this->_table->getOption('parents'), array($this->_table->getComponentName()));
$localIdentifierColumnNames = $this->_table->getIdentifierColumnNames();
$localIdColumnName = array_pop($localIdentifierColumnNames);
$foreignIdentifierColumnNames = $def['table']->getIdentifierColumnNames();
$foreignIdColumnName = array_pop($foreignIdentifierColumnNames);
if (isset($def['local'])) {
if ( ! isset($def['foreign'])) {
// local key is set, but foreign key is not
// try to guess the foreign key
if ($def['local'] === $this->_table->getIdentifier()) {
if ($def['local'] === $localIdColumnName) {
$def['foreign'] = $this->guessColumns($localClasses, $def['table']);
} else {
// the foreign field is likely to be the
// identifier of the foreign class
$def['foreign'] = $def['table']->getIdentifier();
$def['foreign'] = $foreignIdColumnName;
$def['localKey'] = true;
}
} else {
if ($def['local'] !== $this->_table->getIdentifier() &&
if ($def['local'] !== $localIdColumnName &&
$def['type'] == Doctrine_Relation::ONE) {
$def['localKey'] = true;
}
......@@ -394,15 +404,15 @@ class Doctrine_Relation_Parser
if (isset($def['foreign'])) {
// local key not set, but foreign key is set
// try to guess the local key
if ($def['foreign'] === $def['table']->getIdentifier()) {
if ($def['foreign'] === $foreignIdColumnName) {
$def['localKey'] = true;
try {
$def['local'] = $this->guessColumns($foreignClasses, $this->_table);
} catch (Doctrine_Relation_Exception $e) {
$def['local'] = $this->_table->getIdentifier();
$def['local'] = $localIdColumnName;
}
} else {
$def['local'] = $this->_table->getIdentifier();
$def['local'] = $localIdColumnName;
}
} else {
// neither local or foreign key is being set
......@@ -412,16 +422,17 @@ class Doctrine_Relation_Parser
// the following loops are needed for covering inheritance
foreach ($localClasses as $class) {
$table = $conn->getTable($class);
$table = $conn->getTable($class);
$identifierColumnNames = $table->getIdentifierColumnNames();
$idColumnName = array_pop($identifierColumnNames);
$column = strtolower($table->getComponentName())
. '_' . $table->getIdentifier();
. '_' . $idColumnName;
foreach ($foreignClasses as $class2) {
$table2 = $conn->getTable($class2);
if ($table2->hasColumn($column)) {
$def['foreign'] = $column;
$def['local'] = $table->getIdentifier();
$def['local'] = $idColumnName;
return $def;
}
}
......@@ -429,13 +440,15 @@ class Doctrine_Relation_Parser
foreach ($foreignClasses as $class) {
$table = $conn->getTable($class);
$identifierColumnNames = $table->getIdentifierColumnNames();
$idColumnName = array_pop($identifierColumnNames);
$column = strtolower($table->getComponentName())
. '_' . $table->getIdentifier();
. '_' . $idColumnName;
foreach ($localClasses as $class2) {
$table2 = $conn->getTable($class2);
if ($table2->hasColumn($column)) {
$def['foreign'] = $table->getIdentifier();
$def['foreign'] = $idColumnName;
$def['local'] = $column;
$def['localKey'] = true;
return $def;
......@@ -445,11 +458,12 @@ class Doctrine_Relation_Parser
// auto-add columns and auto-build relation
$columns = array();
foreach ((array) $this->_table->getIdentifier() as $id) {
foreach ((array) $this->_table->getIdentifierColumnNames() as $id) {
// ?? should this not be $this->_table->getComponentName() ??
$column = strtolower($table->getComponentName())
. '_' . $id;
$col = $this->_table->getDefinitionOf($id);
$col = $this->_table->getColumnDefinition($id);
$type = $col['type'];
$length = $col['length'];
......@@ -468,7 +482,7 @@ class Doctrine_Relation_Parser
} else {
$def['foreign'] = $columns[0];
}
$def['local'] = $this->_table->getIdentifier();
$def['local'] = $localIdColumnName;
}
}
return $def;
......
......@@ -40,9 +40,9 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
protected $_data = array();
/**
* @var mixed $identifier
* @var mixed $identifier The field names of all fields that are part of the identifier/primary key
*/
protected $_identifier;
protected $_identifier = array();
/**
* @see Doctrine_Identifier constants
......@@ -67,7 +67,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
/**
* @var array $columns an array of column definitions,
* keys as column names and values as column definitions
* keys are column names and values are column definitions
*
* the definition array has atleast the following values:
*
......@@ -83,10 +83,20 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
protected $_columns = array();
/**
* @var array $columnAliases an array of column aliases
* keys as column aliases and values as column names
* @var array $_fieldNames an array of field names. used to look up field names
* from column names.
* keys are column names and values are field names
*/
protected $_columnAliases = array();
protected $_fieldNames = array();
/**
*
* @var array $_columnNames an array of column names
* keys are field names and values column names.
* used to look up column names from field names.
* this is the reverse lookup map of $_fieldNames.
*/
protected $_columnNames = array();
/**
* @var integer $columnCount cached column count, Doctrine_Record uses this column count in when
......@@ -202,7 +212,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
$this->_parser = new Doctrine_Relation_Parser($this);
if ($initDefinition) {
$record = $this->initDefinition($name);
$record = $this->initDefinition();
$this->initIdentifier();
......@@ -216,8 +226,15 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
$this->_filters[] = new Doctrine_Record_Filter_Standard();
$this->_repository = new Doctrine_Table_Repository($this);
}
public function initDefinition($name)
{
/**
* Initializes the in-memory table definition.
*
* @param string $name
*/
public function initDefinition()
{
$name = $this->_options['name'];
if ( ! class_exists($name) || empty($name)) {
throw new Doctrine_Exception("Couldn't find class " . $name);
}
......@@ -253,15 +270,16 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
$record->setTableDefinition();
// get the declaring class of setTableDefinition method
$method = new ReflectionMethod($this->_options['name'], 'setTableDefinition');
$class = $method->getDeclaringClass();
$class = $method->getDeclaringClass();
} else {
$class = new ReflectionClass($class);
}
$this->_options['joinedParents'] = array();
foreach (array_reverse($this->_options['parents']) as $parent) {
if ($parent === $class->getName()) {
continue;
}
......@@ -270,25 +288,25 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
if ($ref->isAbstract()) {
continue;
}
$table = $this->_conn->getTable($parent);
$parentTable = $this->_conn->getTable($parent);
$found = false;
$columns = $table->getColumns();
$parentColumns = $parentTable->getColumns();
foreach ($columns as $column => $definition) {
foreach ($parentColumns as $columnName => $definition) {
if ( ! isset($definition['primary'])) {
if (isset($this->_columns[$column])) {
if (isset($this->_columns[$columnName])) {
$found = true;
break;
} else {
if ( ! isset($columns[$column]['owner'])) {
$columns[$column]['owner'] = $table->getComponentName();
if ( ! isset($parentColumns[$columnName]['owner'])) {
$parentColumns[$columnName]['owner'] = $parentTable->getComponentName();
}
$this->_options['joinedParents'][] = $columns[$column]['owner'];
$this->_options['joinedParents'][] = $parentColumns[$columnName]['owner'];
}
} else {
unset($columns[$column]);
unset($parentColumns[$columnName]);
}
}
......@@ -296,7 +314,10 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
continue;
}
$this->_columns = array_merge($columns, $this->_columns);
foreach ($parentColumns as $columnName => $definition) {
$fullName = $columnName . ' as ' . $parentTable->getFieldName($columnName);
$this->setColumn($fullName, $definition['type'], $definition['length'], $definition, true);
}
break;
}
......@@ -318,6 +339,11 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
return $record;
}
/**
* Initializes the table identifier(s)/primary key(s)
*
*/
public function initIdentifier()
{
switch (count($this->_identifier)) {
......@@ -342,15 +368,16 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
unset($definition['sequence']);
// add the inherited primary key column
$this->_columns = array_merge(array($id => $definition), $this->_columns);
$fullName = $id . ' as ' . $table->getFieldName($id);
$this->setColumn($fullName, $definition['type'], $definition['length'],
$definition, true);
}
} else {
$this->_columns = array_merge(array('id' =>
array('type' => 'integer',
'length' => 20,
'autoincrement' => true,
'primary' => true)), $this->_columns);
$definition = array('type' => 'integer',
'length' => 20,
'autoincrement' => true,
'primary' => true);
$this->setColumn('id', $definition['type'], $definition['length'], $definition, true);
$this->_identifier = 'id';
$this->_identifierType = Doctrine::IDENTIFIER_AUTOINC;
}
......@@ -358,7 +385,8 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
break;
case 1:
foreach ($this->_identifier as $pk) {
$e = $this->_columns[$pk];
$columnName = $this->getColumnName($pk);
$e = $this->_columns[$columnName];
$found = false;
......@@ -404,25 +432,46 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
$this->_identifierType = Doctrine::IDENTIFIER_COMPOSITE;
}
}
public function getColumnOwner($column)
/**
* Gets the owner of a column.
* The owner of a column is the name of the component in a hierarchy that
* defines the column.
*
* @param string $columnName The column name
* @return string The name of the owning/defining component
*/
public function getColumnOwner($columnName)
{
if (isset($this->_columns[$column]['owner'])) {
return $this->_columns[$column]['owner'];
if (isset($this->_columns[$columnName]['owner'])) {
return $this->_columns[$columnName]['owner'];
} else {
return $this->getComponentName();
}
}
public function isInheritedColumn($column)
/**
* Checks whether a column is inherited from a component further up in the hierarchy.
*
* @param $columnName The column name
* @return boolean TRUE if column is inherited, FALSE otherwise.
*/
public function isInheritedColumn($columnName)
{
return (isset($this->_columns[$column]['owner']));
return (isset($this->_columns[$columnName]['owner']));
}
public function isIdentifier($identifier)
/**
* Checks whether a field is part of the table identifier/primary key field(s).
*
* @param string $fieldName The field name
* @return boolean TRUE if the field is part of the table identifier/primary key field(s),
* FALSE otherwise.
*/
public function isIdentifier($fieldName)
{
return ($identifier === $this->_identifier ||
in_array($identifier, (array) $this->_identifier));
return ($fieldName === $this->getIdentifier() ||
in_array($fieldName, (array) $this->getIdentifier()));
}
public function getMethodOwner($method)
......@@ -472,10 +521,9 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
$columns = array();
$primary = array();
foreach ($this->getColumns() as $name => $column) {
$definition = $column;
foreach ($this->getColumns() as $name => $definition) {
if (isset($column['owner'])) {
if (isset($definition['owner'])) {
continue;
}
......@@ -499,52 +547,50 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
}
$options['foreignKeys'] = array();
if ($parseForeignKeys) {
if ($this->getAttribute(Doctrine::ATTR_EXPORT) & Doctrine::EXPORT_CONSTRAINTS) {
$constraints = array();
if ($parseForeignKeys && $this->getAttribute(Doctrine::ATTR_EXPORT)
& Doctrine::EXPORT_CONSTRAINTS) {
$emptyIntegrity = array('onUpdate' => null,
'onDelete' => null);
$constraints = array();
foreach ($this->getRelations() as $name => $relation) {
$fk = $relation->toArray();
$fk['foreignTable'] = $relation->getTable()->getTableName();
$emptyIntegrity = array('onUpdate' => null,
'onDelete' => null);
if ($relation->getTable() === $this && in_array($relation->getLocal(), $primary)) {
if ($relation->hasConstraint()) {
throw new Doctrine_Table_Exception("Badly constructed integrity constraints.");
}
foreach ($this->getRelations() as $name => $relation) {
$fk = $relation->toArray();
$fk['foreignTable'] = $relation->getTable()->getTableName();
continue;
if ($relation->getTable() === $this && in_array($relation->getLocal(), $primary)) {
if ($relation->hasConstraint()) {
throw new Doctrine_Table_Exception("Badly constructed integrity constraints.");
}
continue;
}
$integrity = array('onUpdate' => $fk['onUpdate'],
'onDelete' => $fk['onDelete']);
if ($relation instanceof Doctrine_Relation_LocalKey) {
$def = array('local' => $relation->getLocal(),
'foreign' => $relation->getForeign(),
'foreignTable' => $relation->getTable()->getTableName());
$integrity = array('onUpdate' => $fk['onUpdate'],
'onDelete' => $fk['onDelete']);
if (($key = array_search($def, $options['foreignKeys'])) === false) {
$options['foreignKeys'][] = $def;
if ($relation instanceof Doctrine_Relation_LocalKey) {
$def = array('local' => $relation->getLocal(),
'foreign' => $relation->getForeign(),
'foreignTable' => $relation->getTable()->getTableName());
$constraints[] = $integrity;
} else {
if ($integrity !== $emptyIntegrity) {
$constraints[$key] = $integrity;
}
if (($key = array_search($def, $options['foreignKeys'])) === false) {
$options['foreignKeys'][] = $def;
$constraints[] = $integrity;
} else {
if ($integrity !== $emptyIntegrity) {
$constraints[$key] = $integrity;
}
}
}
}
foreach ($constraints as $k => $def) {
$options['foreignKeys'][$k] = array_merge($options['foreignKeys'][$k], $def);
}
foreach ($constraints as $k => $def) {
$options['foreignKeys'][$k] = array_merge($options['foreignKeys'][$k], $def);
}
}
$options['primary'] = $primary;
return array('tableName' => $this->getOption('tableName'),
......@@ -568,9 +614,8 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
$this->_conn->export->createIndex($this->_options['tableName'], $index, $definition);
}
$this->_conn->commit();
} catch(Doctrine_Connection_Exception $e) {
} catch (Doctrine_Connection_Exception $e) {
$this->_conn->rollback();
throw $e;
}
}
......@@ -676,6 +721,12 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
return false;
}
/**
* DESCRIBE WHAT THIS METHOD DOES, PLEASE!
*
* @todo Name proposal: addRelation
*/
public function bind($args, $type)
{
$options = array();
......@@ -833,14 +884,41 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
* @param string $alias column alias
* @return string column name
*/
public function getColumnName($alias)
public function getColumnName($fieldName)
{
$alias = strtolower($alias);
if (isset($this->_columnAliases[$alias])) {
return $this->_columnAliases[$alias];
if (isset($this->_columnNames[$fieldName])) {
return $this->_columnNames[$fieldName];
}
return $alias;
return $fieldName;
}
/**
*
*
*/
public function getColumnDefinition($columnName)
{
if ( ! isset($this->_columns[$columnName])) {
return false;
}
return $this->_columns[$columnName];
}
/**
* getColumnAlias
*
* returns a column alias for a column name
* if no alias can be found the column name is returned.
*
* @param string $columnName column name
* @return string column alias
*/
public function getFieldName($columnName)
{
if (isset($this->_fieldNames[$columnName])) {
return $this->_fieldNames[$columnName];
}
return $columnName;
}
/**
......@@ -850,10 +928,12 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
* @param string $type
* @param integer $length
* @param mixed $options
* @param boolean $prepend Whether to prepend or append the new column to the column list.
* By default the column gets appended.
* @throws Doctrine_Table_Exception if trying use wrongly typed parameter
* @return void
*/
public function setColumn($name, $type, $length = null, $options = array())
public function setColumn($name, $type, $length = null, $options = array(), $prepend = false)
{
if (is_string($options)) {
$options = explode('|', $options);
......@@ -867,16 +947,17 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
unset($options[$k]);
}
}
$name = strtolower($name);
// extract column name & field name
$parts = explode(' as ', $name);
if (count($parts) > 1) {
$this->_columnAliases[$parts[1]] = $parts[0];
$name = $parts[0];
$fieldName = $parts[1];
} else {
$fieldName = $parts[0];
}
$name = strtolower($parts[0]);
$this->_columnNames[$fieldName] = $name;
$this->_fieldNames[$name] = $fieldName;
if ($length == null) {
switch ($type) {
......@@ -905,13 +986,23 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
break;
}
}
$this->_columns[$name] = $options;
$this->_columns[$name]['type'] = $type;
$this->_columns[$name]['length'] = $length;
$options['type'] = $type;
$options['length'] = $length;
if ($prepend) {
$this->_columns = array_merge(array($name => $options), $this->_columns);
} else {
$this->_columns[$name] = $options;
}
if (isset($options['primary'])) {
$this->_identifier[] = $name;
if (isset($this->_identifier)) {
$this->_identifier = (array) $this->_identifier;
}
if ( ! in_array($fieldName, $this->_identifier)) {
$this->_identifier[] = $fieldName;
}
}
if (isset($options['default'])) {
$this->hasDefaultValues = true;
......@@ -933,17 +1024,17 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
* getDefaultValueOf
* returns the default value(if any) for given column
*
* @param string $column
* @param string $fieldName
* @return mixed
*/
public function getDefaultValueOf($column)
public function getDefaultValueOf($fieldName)
{
$column = strtolower($column);
if ( ! isset($this->_columns[$column])) {
throw new Doctrine_Table_Exception("Couldn't get default value. Column ".$column." doesn't exist.");
$columnName = $this->getColumnName($fieldName);
if ( ! isset($this->_columns[$columnName])) {
throw new Doctrine_Table_Exception("Couldn't get default value. Column ".$columnName." doesn't exist.");
}
if (isset($this->_columns[$column]['default'])) {
return $this->_columns[$column]['default'];
if (isset($this->_columns[$columnName]['default'])) {
return $this->_columns[$columnName]['default'];
} else {
return null;
}
......@@ -969,9 +1060,9 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
* hasColumn
* @return boolean
*/
public function hasColumn($name)
public function hasColumn($columnName)
{
return isset($this->_columns[$name]);
return isset($this->_columns[$columnName]);
}
/**
......@@ -1030,7 +1121,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
$id = is_array($id) ? array_values($id) : array($id);
return $this->createQuery()
->where(implode(' = ? AND ', (array) $this->_identifier) . ' = ?')
->where(implode(' = ? AND ', $this->getIdentifierColumnNames()) . ' = ?')
->fetchOne($id, $hydrationMode);
}
......@@ -1111,6 +1202,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
* clears the first level cache (identityMap)
*
* @return void
* @todo what about a more descriptive name? clearIdentityMap?
*/
public function clear()
{
......@@ -1167,29 +1259,27 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
public function getRecord()
{
if ( ! empty($this->_data)) {
$this->_data = array_change_key_case($this->_data, CASE_LOWER);
$key = $this->getIdentifier();
$identifierFieldNames = $this->getIdentifier();
if ( ! is_array($key)) {
$key = array($key);
if ( ! is_array($identifierFieldNames)) {
$identifierFieldNames = array($identifierFieldNames);
}
$found = false;
foreach ($key as $k) {
if ( ! isset($this->_data[$k])) {
foreach ($identifierFieldNames as $fieldName) {
if ( ! isset($this->_data[$fieldName])) {
// primary key column not found return new record
$found = true;
break;
}
$id[] = $this->_data[$k];
$id[] = $this->_data[$fieldName];
}
if ($found) {
$recordName = $this->getClassnameToReturn();
$record = new $recordName($this, true);
$this->_data = array();
return $record;
}
......@@ -1210,7 +1300,6 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
$record = new $recordName($this, true);
}
return $record;
}
......@@ -1257,9 +1346,10 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
final public function getProxy($id = null)
{
if ($id !== null) {
$query = 'SELECT ' . implode(', ', (array) $this->_identifier)
$identifierColumnNames = $this->getIdentifierColumnNames();
$query = 'SELECT ' . implode(', ', (array) $identifierColumnNames)
. ' FROM ' . $this->getTableName()
. ' WHERE ' . implode(' = ? && ', (array) $this->_identifier) . ' = ?';
. ' WHERE ' . implode(' = ? && ', (array) $identifierColumnNames) . ' = ?';
$query = $this->applyInheritance($query);
$params = array_merge(array($id), array_values($this->_options['inheritanceMap']));
......@@ -1282,7 +1372,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
if ( ! empty($this->_options['inheritanceMap'])) {
$a = array();
foreach ($this->_options['inheritanceMap'] as $field => $value) {
$a[] = $field . ' = ?';
$a[] = $this->getColumnName($field) . ' = ?';
}
$i = implode(' AND ', $a);
$where .= ' AND ' . $i;
......@@ -1302,7 +1392,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
}
/**
* @return Doctrine_Query a Doctrine_Query object
* @return Doctrine_Query a Doctrine_Query object
*/
public function getQueryObject()
{
......@@ -1312,13 +1402,14 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
}
/**
* @param string $field
* @param string $fieldName
* @return array
*/
public function getEnumValues($field)
public function getEnumValues($fieldName)
{
if (isset($this->_columns[$field]['values'])) {
return $this->_columns[$field]['values'];
$columnName = $this->getColumnName($fieldName);
if (isset($this->_columns[$columnName]['values'])) {
return $this->_columns[$columnName]['values'];
} else {
return array();
}
......@@ -1331,16 +1422,17 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
* @param integer $index
* @return mixed
*/
public function enumValue($field, $index)
public function enumValue($fieldName, $index)
{
if ($index instanceof Doctrine_Null) {
return $index;
}
$columnName = $this->getColumnName($fieldName);
if ( ! $this->_conn->getAttribute(Doctrine::ATTR_USE_NATIVE_ENUM)
&& isset($this->_columns[$field]['values'][$index])
&& isset($this->_columns[$columnName]['values'][$index])
) {
return $this->_columns[$field]['values'][$index];
return $this->_columns[$columnName]['values'][$index];
}
return $index;
......@@ -1353,9 +1445,9 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
* @param mixed $value
* @return mixed
*/
public function enumIndex($field, $value)
public function enumIndex($fieldName, $value)
{
$values = $this->getEnumValues($field);
$values = $this->getEnumValues($fieldName);
$index = array_search($value, $values);
if ($index === false || !$this->_conn->getAttribute(Doctrine::ATTR_USE_NATIVE_ENUM)) {
......@@ -1363,7 +1455,9 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
}
return $value;
}
/* getColumnCount
/**
* getColumnCount
*
* @return integer the number of columns in this table
*/
......@@ -1388,11 +1482,10 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
*
* @return boolean
*/
public function removeColumn($column)
public function removeColumn($columnName)
{
if (isset($this->_columns[$column])) {
unset($this->_columns[$column]);
if (isset($this->_columns[$columnName])) {
unset($this->_columns[$columnName]);
return true;
}
......@@ -1400,13 +1493,41 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
}
/**
* returns an array containing all the column names
* returns an array containing all the column names.
*
* @return array
*/
public function getColumnNames()
public function getColumnNames(array $fieldNames = null)
{
return array_keys($this->_columns);
if ($fieldNames === null) {
return array_keys($this->_columns);
} else {
$columnNames = array();
foreach ($fieldNames as $fieldName) {
$columnNames[] = $this->getColumnName($fieldName);
}
return $columnNames;
}
}
/**
* returns an array with all the identifier column names.
*
* @return array
*/
public function getIdentifierColumnNames()
{
return $this->getColumnNames((array) $this->getIdentifier());
}
/**
* returns an array containing all the field names.
*
* @return array
*/
public function getFieldNames()
{
return array_values($this->_fieldNames);
}
/**
......@@ -1414,12 +1535,10 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
*
* @return mixed array on success, false on failure
*/
public function getDefinitionOf($column)
public function getDefinitionOf($fieldName)
{
if (isset($this->_columns[$column])) {
return $this->_columns[$column];
}
return false;
$columnName = $this->getColumnName($fieldName);
return $this->getColumnDefinition($columnName);
}
/**
......@@ -1427,10 +1546,11 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
*
* @return mixed string on success, false on failure
*/
public function getTypeOf($column)
public function getTypeOf($fieldName)
{
if (isset($this->_columns[$column])) {
return $this->_columns[$column]['type'];
$columnName = $this->getColumnName($fieldName);
if (isset($this->_columns[$columnName])) {
return $this->_columns[$columnName]['type'];
}
return false;
}
......@@ -1482,14 +1602,14 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
* @param string $value field value
* @return mixed prepared value
*/
public function prepareValue($field, $value)
public function prepareValue($fieldName, $value)
{
if ($value === self::$_null) {
return self::$_null;
} elseif ($value === null) {
return null;
} else {
$type = $this->getTypeOf($field);
$type = $this->getTypeOf($fieldName);
switch ($type) {
case 'array':
......@@ -1498,7 +1618,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
$value = unserialize($value);
if ($value === false) {
throw new Doctrine_Table_Exception('Unserialization of ' . $field . ' failed.');
throw new Doctrine_Table_Exception('Unserialization of ' . $fieldName . ' failed.');
}
return $value;
}
......@@ -1507,12 +1627,12 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
$value = gzuncompress($value);
if ($value === false) {
throw new Doctrine_Table_Exception('Uncompressing of ' . $field . ' failed.');
throw new Doctrine_Table_Exception('Uncompressing of ' . $fieldName . ' failed.');
}
return $value;
break;
case 'enum':
return $this->enumValue($field, $value);
return $this->enumValue($fieldName, $value);
break;
case 'boolean':
return (boolean) $value;
......@@ -1706,9 +1826,9 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
* @param string $hydrationMode
* @return void
*/
protected function findBy($column, $value, $hydrationMode = null)
protected function findBy($fieldName, $value, $hydrationMode = null)
{
return $this->createQuery()->where($column . ' = ?')->execute(array($value), $hydrationMode);
return $this->createQuery()->where($fieldName . ' = ?')->execute(array($value), $hydrationMode);
}
/**
......@@ -1719,11 +1839,11 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
* @param string $hydrationMode
* @return void
*/
protected function findOneBy($column, $value, $hydrationMode = null)
protected function findOneBy($fieldName, $value, $hydrationMode = null)
{
$results = $this->createQuery()->where($column . ' = ?')->limit(1)->execute(array($value), $hydrationMode);
$results = $this->createQuery()->where($fieldName . ' = ?')->limit(1)->execute(array($value), $hydrationMode);
return $hydrationMode === Doctrine::FETCH_ARRAY ? $results[0]:$results->getFirst();
return $hydrationMode === Doctrine::FETCH_ARRAY ? $results[0] : $results->getFirst();
}
/**
......@@ -1746,15 +1866,15 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable
}
if (isset($by)) {
if (!isset($arguments[0])) {
if ( ! isset($arguments[0])) {
throw new Doctrine_Table_Exception('You must specify the value to findBy');
}
$column = Doctrine::tableize($by);
$fieldName = Doctrine::tableize($by);
$hydrationMode = isset($arguments[1]) ? $arguments[1]:null;
if ($this->hasColumn($column)) {
return $this->$method($column, $arguments[0], $hydrationMode);
if ($this->hasColumn($fieldName)) {
return $this->$method($fieldName, $arguments[0], $hydrationMode);
} else if ($this->hasRelation($by)) {
$relation = $this->getRelation($by);
......
......@@ -56,6 +56,7 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
/**
* @var array $invalid an array containing all invalid records within this transaction
* @todo What about a more verbose name? $invalidRecords?
*/
protected $invalid = array();
......@@ -294,12 +295,19 @@ class Doctrine_Transaction extends Doctrine_Connection_Module
* @param string $savepoint name of a savepoint to rollback to
* @throws Doctrine_Transaction_Exception if the rollback operation fails at database level
* @return boolean false if rollback couldn't be performed, true otherwise
* @todo Shouldnt this method only commit a rollback if the transactionLevel is 1
* (STATE_ACTIVE)? Explanation: Otherwise a rollback that is triggered from inside doctrine
* in an (emulated) nested transaction would lead to a complete database level
* rollback even though the client code did not yet want to do that.
* In other words: if the user starts a transaction doctrine shouldnt roll it back.
* Doctrine should only roll back transactions started by doctrine. Thoughts?
*/
public function rollback($savepoint = null)
{
$this->conn->connect();
if ($this->transactionLevel == 0) {
$currentState = $this->getState();
if ($currentState != self::STATE_ACTIVE && $currentState != self::STATE_BUSY) {
return false;
}
......
......@@ -4,9 +4,12 @@ class ColumnAliasTest extends Doctrine_Record
public function setTableDefinition()
{
$this->hasColumn('column1 as alias1', 'string', 200);
$this->hasColumn('column2 as alias2', 'integer', 11);
$this->hasColumn('column2 as alias2', 'integer', 4);
$this->hasColumn('another_column as anotherField', 'string', 50);
$this->hasColumn('book_id as bookId', 'integer', 4);
}
public function setUp()
public function setUp()
{
$this->hasOne('Book as book', array('local' => 'book_id', 'foreign' => 'id'));
}
}
......@@ -48,7 +48,7 @@ class Doctrine_Access_TestCase extends Doctrine_UnitTestCase
public function testIsset()
{
$user = new User();
$this->assertTrue(isset($user->name));
$this->assertFalse(isset($user->unknown));
......@@ -70,7 +70,7 @@ class Doctrine_Access_TestCase extends Doctrine_UnitTestCase
public function testOffsetMethods()
{
$user = new User();
$this->assertEqual($user['name'],null);
$this->assertEqual($user['name'], null);
$user['name'] = 'Jack';
$this->assertEqual($user['name'], 'Jack');
......
......@@ -109,7 +109,7 @@ class Doctrine_ClassTableInheritance_TestCase extends Doctrine_UnitTestCase
$q = new Doctrine_Query();
$q->from('CTITest c')->where('c.id = 1');
$this->assertEqual($q->getSql(), 'SELECT c.id AS c__id, c2.name AS c__name, c2.verified AS c__verified, c3.added AS c__added, c.age AS c__age FROM c_t_i_test_parent4 c LEFT JOIN c_t_i_test_parent2 c2 ON c.id = c2.id LEFT JOIN c_t_i_test_parent3 c3 ON c.id = c3.id WHERE c.id = 1');
$this->assertEqual($q->getSql(), 'SELECT c.id AS c__id, c3.added AS c__added, c2.name AS c__name, c2.verified AS c__verified, c.age AS c__age FROM c_t_i_test_parent4 c LEFT JOIN c_t_i_test_parent2 c2 ON c.id = c2.id LEFT JOIN c_t_i_test_parent3 c3 ON c.id = c3.id WHERE c.id = 1');
$record = $q->fetchOne();
......
......@@ -33,14 +33,60 @@
class Doctrine_ColumnAlias_TestCase extends Doctrine_UnitTestCase
{
public function prepareData()
{ }
{
$book1 = new Book();
$book1->name = 'Das Boot';
$book1->save();
$record1 = new ColumnAliasTest();
$record1->alias1 = 'first';
$record1->alias2 = 123;
$record1->anotherField = 'camelCase';
$record1->bookId = $book1->id;
$record1->save();
$record2 = new ColumnAliasTest();
$record2->alias1 = 'one';
$record2->alias2 = 456;
$record2->anotherField = 'KoQ';
$record2->save();
$record2->anotherField = 'foo';
}
public function prepareTables()
{
$this->tables = array('ColumnAliasTest');
$this->tables = array('ColumnAliasTest', 'Book');
parent::prepareTables();
}
public function testAliasesAreSupportedForJoins()
{
$q = new Doctrine_Query();
$q->select('c.*, b.name')->from('ColumnAliasTest c')
->innerJoin('c.book b')
->where('c.anotherField = ?', 'camelCase');
$result = $q->execute();
$this->assertTrue(isset($result[0]->book));
$this->assertEqual($result[0]->book->name, 'Das Boot');
}
public function testAliasesAreSupportedForArrayFetching()
{
$q = new Doctrine_Query();
$q->select('c.*, b.name')->from('ColumnAliasTest c')
->innerJoin('c.book b')
->where('c.anotherField = ?', 'camelCase')
->setHydrationMode(Doctrine::HYDRATE_ARRAY);
$result = $q->execute();
$this->assertEqual($result[0]['alias1'], 'first');
$this->assertEqual($result[0]['alias2'], 123);
$this->assertEqual($result[0]['anotherField'], 'camelCase');
$this->assertTrue(isset($result[0]['book']));
$this->assertEqual($result[0]['book']['name'], 'Das Boot');
}
public function testAliasesAreSupportedForRecordPropertyAccessors()
{
$record = new ColumnAliasTest;
......@@ -50,58 +96,60 @@ class Doctrine_ColumnAlias_TestCase extends Doctrine_UnitTestCase
$this->assertEqual($record->alias1, 'someone');
$this->assertEqual($record->alias2, 187);
} catch(Doctrine_Record_Exception $e) {
} catch (Doctrine_Record_Exception $e) {
$this->fail();
}
$record->save();
}
public function testAliasesAreSupportedForDqlSelectPart()
{
$q = new Doctrine_Query();
$q->select('c.alias1, c.alias2')->from('ColumnAliasTest c');
$q->select('c.alias1, c.alias2, c.anotherField')->from('ColumnAliasTest c');
$coll = $q->execute();
$this->assertEqual($coll[0]->alias1, 'someone');
$this->assertEqual($coll[0]->alias2, 187);
$this->assertEqual($coll[0]->alias1, 'first');
$this->assertEqual($coll[0]->alias2, 123);
$this->assertEqual($coll[0]->anotherField, 'camelCase');
}
public function testAliasesAreSupportedForDqlWherePart()
{
$q = new Doctrine_Query();
$q->select('c.alias1, c.alias2')
$q->select('c.alias1, c.alias2, c.anotherField')
->from('ColumnAliasTest c')
->where('c.alias1 = ?');
->where('c.anotherField = ?');
$coll = $q->execute(array('someone'));
$coll = $q->execute(array('KoQ'));
$this->assertEqual($coll[0]->alias1, 'someone');
$this->assertEqual($coll[0]->alias2, 187);
$this->assertEqual($coll[0]->alias1, 'one');
$this->assertEqual($coll[0]->alias2, 456);
$this->assertEqual($coll[0]->anotherField, 'KoQ');
}
public function testAliasesAreSupportedForDqlAggregateFunctions()
{
$q = new Doctrine_Query();
$q->select('MAX(c.alias1)')
->from('ColumnAliasTest c');
$q->select('MAX(c.alias2)')->from('ColumnAliasTest c');
$coll = $q->execute();
$this->assertEqual($coll[0]->max, 'someone');
$this->assertEqual($coll[0]->MAX, 456);
}
public function testAliasesAreSupportedForDqlHavingPart()
{
$q = new Doctrine_Query();
$q->select('c.alias1')
$q->select('c.alias2')
->from('ColumnAliasTest c')
->having('MAX(c.alias2) = 187')
->groupby('c.id');
->groupby('c.id')
->having('c.alias2 > 123');
$coll = $q->execute();
$this->assertEqual($coll[0]->alias1, 'someone');
$this->assertEqual($coll[0]->alias2, 456);
}
}
......@@ -100,8 +100,8 @@ class Doctrine_Export_Record_TestCase extends Doctrine_UnitTestCase
$this->assertEqual($this->adapter->pop(), 'COMMIT');
$this->assertEqual($this->adapter->pop(), 'ALTER TABLE cms__category_languages ADD FOREIGN KEY (category_id) REFERENCES cms__category(id) ON DELETE CASCADE');
$this->assertEqual($this->adapter->pop(), 'CREATE TABLE cms__category (id BIGINT AUTO_INCREMENT, created DATETIME, parent BIGINT, position MEDIUMINT, active BIGINT, INDEX index_parent_idx (parent), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = INNODB');
$this->assertEqual($this->adapter->pop(), 'CREATE TABLE cms__category_languages (id BIGINT AUTO_INCREMENT, name TEXT, category_id BIGINT, language_id BIGINT, INDEX index_category_idx (category_id), INDEX index_language_idx (language_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = INNODB');
$this->assertEqual($this->adapter->pop(), 'CREATE TABLE cms__category (id BIGINT AUTO_INCREMENT, created DATETIME, parent BIGINT, position MEDIUMINT, active BIGINT, INDEX index_parent_idx (parent), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = INNODB');
$this->assertEqual($this->adapter->pop(), 'BEGIN TRANSACTION');
}
......
......@@ -280,3 +280,4 @@ $data->addTestCase(new Doctrine_Data_Export_TestCase());
$test->addTestCase($data);
$test->run();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment