diff --git a/lib/Doctrine/Collection.php b/lib/Doctrine/Collection.php index 86af3cee5..283c646bc 100644 --- a/lib/Doctrine/Collection.php +++ b/lib/Doctrine/Collection.php @@ -1,769 +1,769 @@ -. - */ -Doctrine::autoload("Doctrine_Access"); -/** - * Doctrine_Collection - * Collection of Doctrine_Record objects. - * - * @package Doctrine - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @category Object Relational Mapping - * @link www.phpdoctrine.com - * @since 1.0 - * @version $Revision$ - * @author Konsta Vesterinen - */ -class Doctrine_Collection extends Doctrine_Access implements Countable, IteratorAggregate, Serializable -{ - /** - * @var array $data an array containing the data access objects of this collection - */ - protected $data = array(); - /** - * @var Doctrine_Table $table each collection has only records of specified table - */ - protected $table; - /** - * @var Doctrine_Record $reference collection can belong to a record - */ - protected $reference; - /** - * @var string $reference_field the reference field of the collection - */ - protected $reference_field; - /** - * @var Doctrine_Relation the record this collection is related to, if any - */ - protected $relation; - /** - * @var boolean $expandable whether or not this collection has been expanded - */ - protected $expandable = true; - /** - * @var array $expanded - */ - protected $expanded = array(); - /** - * @var string $keyColumn the name of the column that is used for collection key mapping - */ - protected $keyColumn; - /** - * @var Doctrine_Null $null used for extremely fast null value testing - */ - protected static $null; - - protected $aggregateValues = array(); - - /** - * constructor - * - * @param Doctrine_Table|string $table - */ - public function __construct($table) - { - if ( ! ($table instanceof Doctrine_Table)) { - $table = Doctrine_Manager::getInstance() - ->getCurrentConnection() - ->getTable($table); - } - $this->table = $table; - - $name = $table->getAttribute(Doctrine::ATTR_COLL_KEY); - if ($name !== null) { - $this->keyColumn = $name; - } - } - /** - * initNullObject - * initializes the null object for this collection - * - * @return void - */ - public static function initNullObject(Doctrine_Null $null) - { - self::$null = $null; - } - /** - * getTable - * returns the table this collection belongs to - * - * @return Doctrine_Table - */ - public function getTable() - { - return $this->table; - } - /** - * setAggregateValue - * - * @param string $name - * @param string $value - * @return void - */ - public function setAggregateValue($name, $value) - { - $this->aggregateValues[$name] = $value; - } - /** - * getAggregateValue - * - * @param string $name - * @return mixed - */ - public function getAggregateValue($name) - { - return $this->aggregateValues[$name]; - } - /** - * this method is automatically called when this Doctrine_Collection is serialized - * - * @return array - */ - public function serialize() - { - $vars = get_object_vars($this); - - unset($vars['reference']); - unset($vars['reference_field']); - unset($vars['relation']); - unset($vars['expandable']); - unset($vars['expanded']); - unset($vars['generator']); - - $vars['table'] = $vars['table']->getComponentName(); - - return serialize($vars); - } - /** - * unseralize - * this method is automatically called everytime a Doctrine_Collection object is unserialized - * - * @return void - */ - public function unserialize($serialized) - { - $manager = Doctrine_Manager::getInstance(); - $connection = $manager->getCurrentConnection(); - - $array = unserialize($serialized); - - foreach ($array as $name => $values) { - $this->$name = $values; - } - - $this->table = $connection->getTable($this->table); - - $this->expanded = array(); - $this->expandable = true; - - $name = $this->table->getAttribute(Doctrine::ATTR_COLL_KEY); - if ($name !== null) { - $this->keyColumn = $name; - } - } - /** - * isExpanded - * - * whether or not an offset batch has been expanded - * @return boolean - */ - public function isExpanded($offset) - { - return isset($this->expanded[$offset]); - } - /** - * isExpandable - * - * whether or not this collection is expandable - * @return boolean - */ - public function isExpandable() - { - return $this->expandable; - } - /** - * setKeyColumn - * - * @param string $column - * @return void - */ - public function setKeyColumn($column) - { - $this->keyColumn = $column; - } - /** - * getKeyColumn - * returns the name of the key column - * - * @return string - */ - public function getKeyColumn() - { - return $this->column; - } - /** - * returns all the records as an array - * - * @return array - */ - public function getData() - { - return $this->data; - } - /** - * @param array $data - */ - public function addData(array $data) - { - $this->data[] = $data; - } - /** - * getFirst - * returns the first record in the collection - * - * @return mixed - */ - public function getFirst() - { - return reset($this->data); - } - /** - * getLast - * returns the last record in the collection - * - * @return mixed - */ - public function getLast() - { - return end($this->data); - } - /** - * setReference - * sets a reference pointer - * - * @return void - */ - public function setReference(Doctrine_Record $record,Doctrine_Relation $relation) - { - $this->reference = $record; - $this->relation = $relation; - - if ($relation instanceof Doctrine_Relation_ForeignKey - || $relation instanceof Doctrine_Relation_LocalKey - ) { - - $this->reference_field = $relation->getForeign(); - - $value = $record->get($relation->getLocal()); - - foreach ($this->getNormalIterator() as $record) { - if ($value !== null) { - $record->set($this->reference_field, $value, false); - } else { - $record->set($this->reference_field, $this->reference, false); - } - } - } elseif ($relation instanceof Doctrine_Relation_Association) { - - } - } - /** - * getReference - * - * @return mixed - */ - public function getReference() - { - return $this->reference; - } - /** - * expand - * expands the collection - * - * @return boolean - */ - public function expand($key) - { - $where = array(); - $params = array(); - $limit = null; - $offset = null; - - switch (get_class($this)) { - case "Doctrine_Collection_Offset": - $limit = $this->getLimit(); - $offset = (floor($key / $limit) * $limit); - - if ( ! $this->expandable && isset($this->expanded[$offset])) { - return false; - } - $fields = implode(", ",$this->table->getColumnNames()); - break; - default: - if ( ! $this->expandable) { - return false; - } - - if ( ! isset($this->reference)) { - return false; - } - - $id = $this->reference->obtainIdentifier(); - - if (empty($id)) { - return false; - } - - switch (get_class($this)) { - case "Doctrine_Collection_Immediate": - $fields = implode(", ",$this->table->getColumnNames()); - break; - default: - $fields = implode(", ",$this->table->getPrimaryKeys()); - }; - }; - - if (isset($this->relation)) { - if ($this->relation instanceof Doctrine_Relation_ForeignKey) { - $params[] = $this->reference->getIncremented(); - $where[] = $this->reference_field." = ?"; - - if ( ! isset($offset)) { - $ids = $this->getPrimaryKeys(); - - if ( ! empty($ids)) { - $where[] = $this->table->getIdentifier()." NOT IN (".substr(str_repeat("?, ",count($ids)),0,-2).")"; - $params = array_merge($params,$ids); - } - - $this->expandable = false; - } - - } elseif ($this->relation instanceof Doctrine_Relation_Association) { - - $asf = $this->relation->getAssociationFactory(); - $query = 'SELECT '.$foreign." FROM ".$asf->getTableName()." WHERE ".$local."=".$this->getIncremented(); - - $table = $fk->getTable(); - $graph = new Doctrine_Query($table->getConnection()); - - $q = 'FROM ' . $table->getComponentName() . ' WHERE ' . $table->getComponentName() . '.' . $table->getIdentifier()." IN ($query)"; - - } - } - - $query = "SELECT ".$fields." FROM ".$this->table->getTableName(); - - // apply column aggregation inheritance - foreach ($this->table->getInheritanceMap() as $k => $v) { - $where[] = $k." = ?"; - $params[] = $v; - } - if ( ! empty($where)) { - $query .= " WHERE ".implode(" AND ",$where); - } - - $coll = $this->table->execute($query, $params, $limit, $offset); - - if ( ! isset($offset)) { - foreach ($coll as $record) { - if (isset($this->reference_field)) { - $record->set($this->reference_field,$this->reference, false); - } - $this->reference->addReference($record, $this->relation); - } - } else { - $i = $offset; - - foreach ($coll as $record) { - if (isset($this->reference)) { - $this->reference->addReference($record, $this->relation, $i); - } else { - $this->data[$i] = $record; - } - $i++; - } - - $this->expanded[$offset] = true; - - // check if the fetched collection's record count is smaller - // than the query limit, if so this collection has been expanded to its max size - - if (count($coll) < $limit) { - $this->expandable = false; - } - } - - return $coll; - } - /** - * remove - * removes a specified collection element - * - * @param mixed $key - * @return boolean - */ - public function remove($key) - { - if ( ! isset($this->data[$key])) { - $this->expand($key); - - throw new Doctrine_Collection_Exception('Unknown key ' . $key); - } - - $removed = $this->data[$key]; - - unset($this->data[$key]); - return $removed; - } - /** - * contains - * whether or not this collection contains a specified element - * - * @param mixed $key the key of the element - * @return boolean - */ - public function contains($key) - { - return isset($this->data[$key]); - } - /** - * get - * returns a record for given key - * - * There are two special cases: - * - * 1. if null is given as a key a new record is created and attached - * at the end of the collection - * - * 2. if given key does not exist, then a new record is create and attached - * to the given key - * - * Collection also maps referential information to newly created records - * - * @param mixed $key the key of the element - * @return Doctrine_Record return a specified record - */ - public function get($key) - { - if($key === null) { - $record = $this->table->create(); - - if (isset($this->reference_field)) { - $record->set($this->reference_field, $this->reference, false); - } - - $this->data[] = $record; - - return $record; - } - - - if ( ! isset($this->data[$key])) { - $this->expand($key); - - if ( ! isset($this->data[$key])) { - $this->data[$key] = $this->table->create(); - } - if (isset($this->reference_field)) { - $value = $this->reference->get($this->relation->getLocal()); - - if ($value !== null) { - $this->data[$key]->set($this->reference_field, $value, false); - } else { - - $this->data[$key]->set($this->reference_field, $this->reference, false); - } - } - } - - return $this->data[$key]; - } - - /** - * @return array an array containing all primary keys - */ - public function getPrimaryKeys() - { - $list = array(); - $name = $this->table->getIdentifier(); - - foreach ($this->data as $record) { - if (is_array($record) && isset($record[$name])) { - $list[] = $record[$name]; - } else { - $list[] = $record->getIncremented(); - } - }; - return $list; - } - /** - * returns all keys - * @return array - */ - public function getKeys() - { - return array_keys($this->data); - } - /** - * count - * this class implements interface countable - * returns the number of records in this collection - * - * @return integer - */ - public function count() - { - return count($this->data); - } - /** - * set - * @param integer $key - * @param Doctrine_Record $record - * @return void - */ - public function set($key, Doctrine_Record $record) - { - if (isset($this->reference_field)) { - $record->set($this->reference_field, $this->reference, false); - } - $this->data[$key] = $record; - } - /** - * adds a record to collection - * @param Doctrine_Record $record record to be added - * @param string $key optional key for the record - * @return boolean - */ - public function add(Doctrine_Record $record,$key = null) - { - if (isset($this->reference_field)) { - $record->set($this->reference_field, $this->reference, false); - } - /** - * for some weird reason in_array cannot be used here (php bug ?) - * - * if used it results in fatal error : [ nesting level too deep ] - */ - foreach ($this->data as $val) { - if ($val === $record) { - return false; - } - } - - if (isset($key)) { - if (isset($this->data[$key])) { - return false; - } - $this->data[$key] = $record; - return true; - } - - if (isset($this->keyColumn)) { - $value = $record->get($this->keyColumn); - if ($value === null) { - throw new Doctrine_Collection_Exception("Couldn't create collection index. Record field '".$this->keyColumn."' was null."); - } - $this->data[$value] = $record; - } else { - $this->data[] = $record; - } - return true; - } - /** - * loadRelated - * - * @param mixed $name - * @return boolean - */ - public function loadRelated($name = null) - { - $query = new Doctrine_Query($this->table->getConnection()); - - if ( ! isset($name)) { - foreach ($this->data as $record) { - $value = $record->getIncremented(); - if ($value !== null) { - $list[] = $value; - } - }; - $query->from($this->table->getComponentName()."(".implode(", ",$this->table->getPrimaryKeys()).")"); - $query->where($this->table->getComponentName().".id IN (".substr(str_repeat("?, ", count($list)),0,-2).")"); - - return $query; - } - - $rel = $this->table->getRelation($name); - $table = $rel->getTable(); - $foreign = $rel->getForeign(); - $local = $rel->getLocal(); - - $list = array(); - if ($rel instanceof Doctrine_Relation_LocalKey || $rel instanceof Doctrine_Relation_ForeignKey) { - foreach ($this->data as $record) { - $list[] = $record[$local]; - }; - } else { - foreach ($this->data as $record) { - $value = $record->getIncremented(); - if ($value !== null) { - $list[] = $value; - } - }; - } - $this->table->getRelation($name); - $dql = $rel->getRelationDql(count($list), 'collection'); - - $coll = $query->query($dql, $list); - - $this->populateRelated($name, $coll); - } - /** - * populateRelated - * - * @param string $name - * @param Doctrine_Collection $coll - * @return void - */ - public function populateRelated($name, Doctrine_Collection $coll) - { - $rel = $this->table->getRelation($name); - $table = $rel->getTable(); - $foreign = $rel->getForeign(); - $local = $rel->getLocal(); - - if ($rel instanceof Doctrine_Relation_LocalKey) { - foreach ($this->data as $key => $record) { - foreach ($coll as $k => $related) { - if ($related[$foreign] == $record[$local]) { - $this->data[$key]->setRelated($name, $related); - } - } - } - } elseif ($rel instanceof Doctrine_Relation_ForeignKey) { - foreach ($this->data as $key => $record) { - if ($record->getState() == Doctrine_Record::STATE_TCLEAN - || $record->getState() == Doctrine_Record::STATE_TDIRTY - ) { - continue; - } - $sub = new Doctrine_Collection($table); - - foreach ($coll as $k => $related) { - if ($related[$foreign] == $record[$local]) { - $sub->add($related); - $coll->remove($k); - } - } - - $this->data[$key]->setRelated($name, $sub); - } - } elseif ($rel instanceof Doctrine_Relation_Association) { - $identifier = $this->table->getIdentifier(); - $asf = $rel->getAssociationFactory(); - $name = $table->getComponentName(); - - foreach ($this->data as $key => $record) { - if ($record->getState() == Doctrine_Record::STATE_TCLEAN - || $record->getState() == Doctrine_Record::STATE_TDIRTY - ) { - continue; - } - $sub = new Doctrine_Collection($table); - foreach ($coll as $k => $related) { - if ($related->get($local) == $record[$identifier]) { - $sub->add($related->get($name)); - } - } - $this->data[$key]->setRelated($name, $sub); - - } - } - } - /** - * getNormalIterator - * returns normal iterator - an iterator that will not expand this collection - * - * @return Doctrine_Iterator_Normal - */ - public function getNormalIterator() - { - return new Doctrine_Collection_Iterator_Normal($this); - } - /** - * save - * saves all records of this collection - * - * @return void - */ - public function save(Doctrine_Connection $conn = null) - { - if ($conn == null) { - $conn = $this->table->getConnection(); - } - $conn->beginTransaction(); - - foreach ($this as $key => $record) { - $record->save(); - }; - - $conn->commit(); - } - /** - * single shot delete - * deletes all records from this collection - * and uses only one database query to perform this operation - * - * @return boolean - */ - public function delete(Doctrine_Connection $conn = null) - { - if ($conn == null) { - $conn = $this->table->getConnection(); - } - - $conn->beginTransaction(); - - foreach ($this as $key => $record) { - $record->delete(); - } - - $conn->commit(); - - $this->data = array(); - } - /** - * getIterator - * @return object ArrayIterator - */ - public function getIterator() - { - $data = $this->data; - return new ArrayIterator($data); - } - /** - * returns a string representation of this object - */ - public function __toString() - { - return Doctrine_Lib::getCollectionAsString($this); - } -} +. + */ +Doctrine::autoload("Doctrine_Access"); +/** + * Doctrine_Collection + * Collection of Doctrine_Record objects. + * + * @package Doctrine + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @category Object Relational Mapping + * @link www.phpdoctrine.com + * @since 1.0 + * @version $Revision$ + * @author Konsta Vesterinen + */ +class Doctrine_Collection extends Doctrine_Access implements Countable, IteratorAggregate, Serializable +{ + /** + * @var array $data an array containing the data access objects of this collection + */ + protected $data = array(); + /** + * @var Doctrine_Table $table each collection has only records of specified table + */ + protected $table; + /** + * @var Doctrine_Record $reference collection can belong to a record + */ + protected $reference; + /** + * @var string $reference_field the reference field of the collection + */ + protected $reference_field; + /** + * @var Doctrine_Relation the record this collection is related to, if any + */ + protected $relation; + /** + * @var boolean $expandable whether or not this collection has been expanded + */ + protected $expandable = true; + /** + * @var array $expanded + */ + protected $expanded = array(); + /** + * @var string $keyColumn the name of the column that is used for collection key mapping + */ + protected $keyColumn; + /** + * @var Doctrine_Null $null used for extremely fast null value testing + */ + protected static $null; + + protected $aggregateValues = array(); + + /** + * constructor + * + * @param Doctrine_Table|string $table + */ + public function __construct($table) + { + if ( ! ($table instanceof Doctrine_Table)) { + $table = Doctrine_Manager::getInstance() + ->getCurrentConnection() + ->getTable($table); + } + $this->table = $table; + + $name = $table->getAttribute(Doctrine::ATTR_COLL_KEY); + if ($name !== null) { + $this->keyColumn = $name; + } + } + /** + * initNullObject + * initializes the null object for this collection + * + * @return void + */ + public static function initNullObject(Doctrine_Null $null) + { + self::$null = $null; + } + /** + * getTable + * returns the table this collection belongs to + * + * @return Doctrine_Table + */ + public function getTable() + { + return $this->table; + } + /** + * setAggregateValue + * + * @param string $name + * @param string $value + * @return void + */ + public function setAggregateValue($name, $value) + { + $this->aggregateValues[$name] = $value; + } + /** + * getAggregateValue + * + * @param string $name + * @return mixed + */ + public function getAggregateValue($name) + { + return $this->aggregateValues[$name]; + } + /** + * this method is automatically called when this Doctrine_Collection is serialized + * + * @return array + */ + public function serialize() + { + $vars = get_object_vars($this); + + unset($vars['reference']); + unset($vars['reference_field']); + unset($vars['relation']); + unset($vars['expandable']); + unset($vars['expanded']); + unset($vars['generator']); + + $vars['table'] = $vars['table']->getComponentName(); + + return serialize($vars); + } + /** + * unseralize + * this method is automatically called everytime a Doctrine_Collection object is unserialized + * + * @return void + */ + public function unserialize($serialized) + { + $manager = Doctrine_Manager::getInstance(); + $connection = $manager->getCurrentConnection(); + + $array = unserialize($serialized); + + foreach ($array as $name => $values) { + $this->$name = $values; + } + + $this->table = $connection->getTable($this->table); + + $this->expanded = array(); + $this->expandable = true; + + $name = $this->table->getAttribute(Doctrine::ATTR_COLL_KEY); + if ($name !== null) { + $this->keyColumn = $name; + } + } + /** + * isExpanded + * + * whether or not an offset batch has been expanded + * @return boolean + */ + public function isExpanded($offset) + { + return isset($this->expanded[$offset]); + } + /** + * isExpandable + * + * whether or not this collection is expandable + * @return boolean + */ + public function isExpandable() + { + return $this->expandable; + } + /** + * setKeyColumn + * + * @param string $column + * @return void + */ + public function setKeyColumn($column) + { + $this->keyColumn = $column; + } + /** + * getKeyColumn + * returns the name of the key column + * + * @return string + */ + public function getKeyColumn() + { + return $this->column; + } + /** + * returns all the records as an array + * + * @return array + */ + public function getData() + { + return $this->data; + } + /** + * @param array $data + */ + public function addData(array $data) + { + $this->data[] = $data; + } + /** + * getFirst + * returns the first record in the collection + * + * @return mixed + */ + public function getFirst() + { + return reset($this->data); + } + /** + * getLast + * returns the last record in the collection + * + * @return mixed + */ + public function getLast() + { + return end($this->data); + } + /** + * setReference + * sets a reference pointer + * + * @return void + */ + public function setReference(Doctrine_Record $record,Doctrine_Relation $relation) + { + $this->reference = $record; + $this->relation = $relation; + + if ($relation instanceof Doctrine_Relation_ForeignKey + || $relation instanceof Doctrine_Relation_LocalKey + ) { + + $this->reference_field = $relation->getForeign(); + + $value = $record->get($relation->getLocal()); + + foreach ($this->getNormalIterator() as $record) { + if ($value !== null) { + $record->set($this->reference_field, $value, false); + } else { + $record->set($this->reference_field, $this->reference, false); + } + } + } elseif ($relation instanceof Doctrine_Relation_Association) { + + } + } + /** + * getReference + * + * @return mixed + */ + public function getReference() + { + return $this->reference; + } + /** + * expand + * expands the collection + * + * @return boolean + */ + public function expand($key) + { + $where = array(); + $params = array(); + $limit = null; + $offset = null; + + switch (get_class($this)) { + case "Doctrine_Collection_Offset": + $limit = $this->getLimit(); + $offset = (floor($key / $limit) * $limit); + + if ( ! $this->expandable && isset($this->expanded[$offset])) { + return false; + } + $fields = implode(", ",$this->table->getColumnNames()); + break; + default: + if ( ! $this->expandable) { + return false; + } + + if ( ! isset($this->reference)) { + return false; + } + + $id = $this->reference->obtainIdentifier(); + + if (empty($id)) { + return false; + } + + switch (get_class($this)) { + case "Doctrine_Collection_Immediate": + $fields = implode(", ",$this->table->getColumnNames()); + break; + default: + $fields = implode(", ",$this->table->getPrimaryKeys()); + }; + }; + + if (isset($this->relation)) { + if ($this->relation instanceof Doctrine_Relation_ForeignKey) { + $params[] = $this->reference->getIncremented(); + $where[] = $this->reference_field." = ?"; + + if ( ! isset($offset)) { + $ids = $this->getPrimaryKeys(); + + if ( ! empty($ids)) { + $where[] = $this->table->getIdentifier()." NOT IN (".substr(str_repeat("?, ",count($ids)),0,-2).")"; + $params = array_merge($params,$ids); + } + + $this->expandable = false; + } + + } elseif ($this->relation instanceof Doctrine_Relation_Association) { + + $asf = $this->relation->getAssociationFactory(); + $query = 'SELECT '.$foreign." FROM ".$asf->getTableName()." WHERE ".$local."=".$this->getIncremented(); + + $table = $fk->getTable(); + $graph = new Doctrine_Query($table->getConnection()); + + $q = 'FROM ' . $table->getComponentName() . ' WHERE ' . $table->getComponentName() . '.' . $table->getIdentifier()." IN ($query)"; + + } + } + + $query = "SELECT ".$fields." FROM ".$this->table->getTableName(); + + // apply column aggregation inheritance + foreach ($this->table->getInheritanceMap() as $k => $v) { + $where[] = $k." = ?"; + $params[] = $v; + } + if ( ! empty($where)) { + $query .= " WHERE ".implode(" AND ",$where); + } + + $coll = $this->table->execute($query, $params, $limit, $offset); + + if ( ! isset($offset)) { + foreach ($coll as $record) { + if (isset($this->reference_field)) { + $record->set($this->reference_field,$this->reference, false); + } + $this->reference->addReference($record, $this->relation); + } + } else { + $i = $offset; + + foreach ($coll as $record) { + if (isset($this->reference)) { + $this->reference->addReference($record, $this->relation, $i); + } else { + $this->data[$i] = $record; + } + $i++; + } + + $this->expanded[$offset] = true; + + // check if the fetched collection's record count is smaller + // than the query limit, if so this collection has been expanded to its max size + + if (count($coll) < $limit) { + $this->expandable = false; + } + } + + return $coll; + } + /** + * remove + * removes a specified collection element + * + * @param mixed $key + * @return boolean + */ + public function remove($key) + { + if ( ! isset($this->data[$key])) { + $this->expand($key); + + throw new Doctrine_Collection_Exception('Unknown key ' . $key); + } + + $removed = $this->data[$key]; + + unset($this->data[$key]); + return $removed; + } + /** + * contains + * whether or not this collection contains a specified element + * + * @param mixed $key the key of the element + * @return boolean + */ + public function contains($key) + { + return isset($this->data[$key]); + } + /** + * get + * returns a record for given key + * + * There are two special cases: + * + * 1. if null is given as a key a new record is created and attached + * at the end of the collection + * + * 2. if given key does not exist, then a new record is create and attached + * to the given key + * + * Collection also maps referential information to newly created records + * + * @param mixed $key the key of the element + * @return Doctrine_Record return a specified record + */ + public function get($key) + { + if ($key === null) { + $record = $this->table->create(); + + if (isset($this->reference_field)) { + $record->set($this->reference_field, $this->reference, false); + } + + $this->data[] = $record; + + return $record; + } + + + if ( ! isset($this->data[$key])) { + $this->expand($key); + + if ( ! isset($this->data[$key])) { + $this->data[$key] = $this->table->create(); + } + if (isset($this->reference_field)) { + $value = $this->reference->get($this->relation->getLocal()); + + if ($value !== null) { + $this->data[$key]->set($this->reference_field, $value, false); + } else { + + $this->data[$key]->set($this->reference_field, $this->reference, false); + } + } + } + + return $this->data[$key]; + } + + /** + * @return array an array containing all primary keys + */ + public function getPrimaryKeys() + { + $list = array(); + $name = $this->table->getIdentifier(); + + foreach ($this->data as $record) { + if (is_array($record) && isset($record[$name])) { + $list[] = $record[$name]; + } else { + $list[] = $record->getIncremented(); + } + }; + return $list; + } + /** + * returns all keys + * @return array + */ + public function getKeys() + { + return array_keys($this->data); + } + /** + * count + * this class implements interface countable + * returns the number of records in this collection + * + * @return integer + */ + public function count() + { + return count($this->data); + } + /** + * set + * @param integer $key + * @param Doctrine_Record $record + * @return void + */ + public function set($key, Doctrine_Record $record) + { + if (isset($this->reference_field)) { + $record->set($this->reference_field, $this->reference, false); + } + $this->data[$key] = $record; + } + /** + * adds a record to collection + * @param Doctrine_Record $record record to be added + * @param string $key optional key for the record + * @return boolean + */ + public function add(Doctrine_Record $record,$key = null) + { + if (isset($this->reference_field)) { + $record->set($this->reference_field, $this->reference, false); + } + /** + * for some weird reason in_array cannot be used here (php bug ?) + * + * if used it results in fatal error : [ nesting level too deep ] + */ + foreach ($this->data as $val) { + if ($val === $record) { + return false; + } + } + + if (isset($key)) { + if (isset($this->data[$key])) { + return false; + } + $this->data[$key] = $record; + return true; + } + + if (isset($this->keyColumn)) { + $value = $record->get($this->keyColumn); + if ($value === null) { + throw new Doctrine_Collection_Exception("Couldn't create collection index. Record field '".$this->keyColumn."' was null."); + } + $this->data[$value] = $record; + } else { + $this->data[] = $record; + } + return true; + } + /** + * loadRelated + * + * @param mixed $name + * @return boolean + */ + public function loadRelated($name = null) + { + $query = new Doctrine_Query($this->table->getConnection()); + + if ( ! isset($name)) { + foreach ($this->data as $record) { + $value = $record->getIncremented(); + if ($value !== null) { + $list[] = $value; + } + }; + $query->from($this->table->getComponentName()."(".implode(", ",$this->table->getPrimaryKeys()).")"); + $query->where($this->table->getComponentName().".id IN (".substr(str_repeat("?, ", count($list)),0,-2).")"); + + return $query; + } + + $rel = $this->table->getRelation($name); + $table = $rel->getTable(); + $foreign = $rel->getForeign(); + $local = $rel->getLocal(); + + $list = array(); + if ($rel instanceof Doctrine_Relation_LocalKey || $rel instanceof Doctrine_Relation_ForeignKey) { + foreach ($this->data as $record) { + $list[] = $record[$local]; + }; + } else { + foreach ($this->data as $record) { + $value = $record->getIncremented(); + if ($value !== null) { + $list[] = $value; + } + }; + } + $this->table->getRelation($name); + $dql = $rel->getRelationDql(count($list), 'collection'); + + $coll = $query->query($dql, $list); + + $this->populateRelated($name, $coll); + } + /** + * populateRelated + * + * @param string $name + * @param Doctrine_Collection $coll + * @return void + */ + public function populateRelated($name, Doctrine_Collection $coll) + { + $rel = $this->table->getRelation($name); + $table = $rel->getTable(); + $foreign = $rel->getForeign(); + $local = $rel->getLocal(); + + if ($rel instanceof Doctrine_Relation_LocalKey) { + foreach ($this->data as $key => $record) { + foreach ($coll as $k => $related) { + if ($related[$foreign] == $record[$local]) { + $this->data[$key]->setRelated($name, $related); + } + } + } + } elseif ($rel instanceof Doctrine_Relation_ForeignKey) { + foreach ($this->data as $key => $record) { + if ($record->getState() == Doctrine_Record::STATE_TCLEAN + || $record->getState() == Doctrine_Record::STATE_TDIRTY + ) { + continue; + } + $sub = new Doctrine_Collection($table); + + foreach ($coll as $k => $related) { + if ($related[$foreign] == $record[$local]) { + $sub->add($related); + $coll->remove($k); + } + } + + $this->data[$key]->setRelated($name, $sub); + } + } elseif ($rel instanceof Doctrine_Relation_Association) { + $identifier = $this->table->getIdentifier(); + $asf = $rel->getAssociationFactory(); + $name = $table->getComponentName(); + + foreach ($this->data as $key => $record) { + if ($record->getState() == Doctrine_Record::STATE_TCLEAN + || $record->getState() == Doctrine_Record::STATE_TDIRTY + ) { + continue; + } + $sub = new Doctrine_Collection($table); + foreach ($coll as $k => $related) { + if ($related->get($local) == $record[$identifier]) { + $sub->add($related->get($name)); + } + } + $this->data[$key]->setRelated($name, $sub); + + } + } + } + /** + * getNormalIterator + * returns normal iterator - an iterator that will not expand this collection + * + * @return Doctrine_Iterator_Normal + */ + public function getNormalIterator() + { + return new Doctrine_Collection_Iterator_Normal($this); + } + /** + * save + * saves all records of this collection + * + * @return void + */ + public function save(Doctrine_Connection $conn = null) + { + if ($conn == null) { + $conn = $this->table->getConnection(); + } + $conn->beginTransaction(); + + foreach ($this as $key => $record) { + $record->save(); + }; + + $conn->commit(); + } + /** + * single shot delete + * deletes all records from this collection + * and uses only one database query to perform this operation + * + * @return boolean + */ + public function delete(Doctrine_Connection $conn = null) + { + if ($conn == null) { + $conn = $this->table->getConnection(); + } + + $conn->beginTransaction(); + + foreach ($this as $key => $record) { + $record->delete(); + } + + $conn->commit(); + + $this->data = array(); + } + /** + * getIterator + * @return object ArrayIterator + */ + public function getIterator() + { + $data = $this->data; + return new ArrayIterator($data); + } + /** + * returns a string representation of this object + */ + public function __toString() + { + return Doctrine_Lib::getCollectionAsString($this); + } +} diff --git a/lib/Doctrine/DataDict/Firebird.php b/lib/Doctrine/DataDict/Firebird.php index 7200904b9..afb07aaf1 100644 --- a/lib/Doctrine/DataDict/Firebird.php +++ b/lib/Doctrine/DataDict/Firebird.php @@ -1,204 +1,205 @@ -. - */ -Doctrine::autoload('Doctrine_DataDict'); -/** - * @package Doctrine - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @author Konsta Vesterinen - * @author Lorenzo Alberton (PEAR MDB2 Interbase driver) - * @author Lukas Smith (PEAR MDB2 library) - * @version $Revision$ - * @category Object Relational Mapping - * @link www.phpdoctrine.com - * @since 1.0 - */ -class Doctrine_DataDict_Firebird extends Doctrine_DataDict -{ - /** - * Obtain DBMS specific SQL code portion needed to declare an text type - * field to be used in statements like CREATE TABLE. - * - * @param array $field associative array with the name of the properties - * of the field being declared as array indexes. Currently, the types - * of supported field properties are as follows: - * - * length - * Integer value that determines the maximum length of the text - * field. If this argument is missing the field should be - * declared to have the longest length allowed by the DBMS. - * - * default - * Text value to be used as default for this field. - * - * notnull - * Boolean flag that indicates whether this field is constrained - * to not be set to null. - * @return string DBMS specific SQL code portion that should be used to - * declare the specified field. - */ - public function getNativeDeclaration($field) - { - switch ($field['type']) { - case 'varchar': - case 'string': - case 'array': - case 'object': - case 'char': - case 'text': - $length = !empty($field['length']) - ? $field['length'] : 16777215; // TODO: $db->options['default_text_field_length']; - - $fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false; - - return $fixed ? 'CHAR('.$length.')' : 'VARCHAR('.$length.')'; - case 'clob': - return 'BLOB SUB_TYPE 1'; - case 'blob': - return 'BLOB SUB_TYPE 0'; - case 'integer': - case 'enum': - return 'INT'; - case 'boolean': - return 'SMALLINT'; - case 'date': - return 'DATE'; - case 'time': - return 'TIME'; - case 'timestamp': - return 'TIMESTAMP'; - case 'float': - return 'DOUBLE PRECISION'; - case 'decimal': - $length = !empty($field['length']) ? $field['length'] : 18; - return 'DECIMAL('.$length.','.$db->options['decimal_places'].')'; - } - return ''; - } - /** - * Maps a native array description of a field to a Doctrine datatype and length - * - * @param array $field native field description - * @return array containing the various possible types, length, sign, fixed - */ - public function getPortableDeclaration($field) - { - $length = (isset($field['length']) && $field['length'] > 0) ? $field['length'] : null; - - $type = array(); - $unsigned = $fixed = null; - $dbType = strtolower($field['type']); - $field['field_sub_type'] = !empty($field['field_sub_type']) - ? strtolower($field['field_sub_type']) : null; - - if( ! isset($field['name'])) - $field['name'] = ''; - - switch ($dbType) { - case 'smallint': - case 'integer': - case 'int64': - //these may be 'numeric' or 'decimal' - if (isset($field['field_sub_type'])) { - $field['type'] = $field['field_sub_type']; - return $this->getPortableDeclaration($field); - } - case 'bigint': - case 'quad': - $type[] = 'integer'; - if ($length == '1') { - $type[] = 'boolean'; - if (preg_match('/^(is|has)/', $field['name'])) { - $type = array_reverse($type); - } - } - break; - case 'varchar': - $fixed = false; - case 'char': - case 'cstring': - $type[] = 'string'; - if ($length == '1') { - $type[] = 'boolean'; - if (preg_match('/^(is|has)/', $field['name'])) { - $type = array_reverse($type); - } - } - if ($fixed !== false) { - $fixed = true; - } - break; - case 'date': - $type[] = 'date'; - $length = null; - break; - case 'timestamp': - $type[] = 'timestamp'; - $length = null; - break; - case 'time': - $type[] = 'time'; - $length = null; - break; - case 'float': - case 'double': - case 'double precision': - case 'd_float': - $type[] = 'float'; - break; - case 'decimal': - case 'numeric': - $type[] = 'decimal'; - break; - case 'blob': - $type[] = ($field['field_sub_type'] == 'text') ? 'clob' : 'blob'; - $length = null; - break; - default: - throw new Doctrine_DataDict_Firebird_Exception('unknown database attribute type: '.$dbType); - } - - return array($type, $length, $unsigned, $fixed); - } - /** - * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET - * of a field declaration to be used in statements like CREATE TABLE. - * - * @param string $charset name of the charset - * @return string DBMS specific SQL code portion needed to set the CHARACTER SET - * of a field declaration. - */ - public function getCharsetFieldDeclaration($charset) - { - return 'CHARACTER SET '.$charset; - } - /** - * Obtain DBMS specific SQL code portion needed to set the COLLATION - * of a field declaration to be used in statements like CREATE TABLE. - * - * @param string $collation name of the collation - * @return string DBMS specific SQL code portion needed to set the COLLATION - * of a field declaration. - */ - public function getCollationFieldDeclaration($collation) - { - return 'COLLATE '.$collation; - } -} +. + */ +Doctrine::autoload('Doctrine_DataDict'); +/** + * @package Doctrine + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @author Konsta Vesterinen + * @author Lorenzo Alberton (PEAR MDB2 Interbase driver) + * @author Lukas Smith (PEAR MDB2 library) + * @version $Revision$ + * @category Object Relational Mapping + * @link www.phpdoctrine.com + * @since 1.0 + */ +class Doctrine_DataDict_Firebird extends Doctrine_DataDict +{ + /** + * Obtain DBMS specific SQL code portion needed to declare an text type + * field to be used in statements like CREATE TABLE. + * + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + */ + public function getNativeDeclaration($field) + { + switch ($field['type']) { + case 'varchar': + case 'string': + case 'array': + case 'object': + case 'char': + case 'text': + $length = !empty($field['length']) + ? $field['length'] : 16777215; // TODO: $db->options['default_text_field_length']; + + $fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false; + + return $fixed ? 'CHAR('.$length.')' : 'VARCHAR('.$length.')'; + case 'clob': + return 'BLOB SUB_TYPE 1'; + case 'blob': + return 'BLOB SUB_TYPE 0'; + case 'integer': + case 'enum': + return 'INT'; + case 'boolean': + return 'SMALLINT'; + case 'date': + return 'DATE'; + case 'time': + return 'TIME'; + case 'timestamp': + return 'TIMESTAMP'; + case 'float': + return 'DOUBLE PRECISION'; + case 'decimal': + $length = !empty($field['length']) ? $field['length'] : 18; + return 'DECIMAL('.$length.','.$db->options['decimal_places'].')'; + } + return ''; + } + /** + * Maps a native array description of a field to a Doctrine datatype and length + * + * @param array $field native field description + * @return array containing the various possible types, length, sign, fixed + */ + public function getPortableDeclaration($field) + { + $length = (isset($field['length']) && $field['length'] > 0) ? $field['length'] : null; + + $type = array(); + $unsigned = $fixed = null; + $dbType = strtolower($field['type']); + $field['field_sub_type'] = !empty($field['field_sub_type']) + ? strtolower($field['field_sub_type']) : null; + + if ( ! isset($field['name'])) { + $field['name'] = ''; + } + + switch ($dbType) { + case 'smallint': + case 'integer': + case 'int64': + //these may be 'numeric' or 'decimal' + if (isset($field['field_sub_type'])) { + $field['type'] = $field['field_sub_type']; + return $this->getPortableDeclaration($field); + } + case 'bigint': + case 'quad': + $type[] = 'integer'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } + break; + case 'varchar': + $fixed = false; + case 'char': + case 'cstring': + $type[] = 'string'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } + if ($fixed !== false) { + $fixed = true; + } + break; + case 'date': + $type[] = 'date'; + $length = null; + break; + case 'timestamp': + $type[] = 'timestamp'; + $length = null; + break; + case 'time': + $type[] = 'time'; + $length = null; + break; + case 'float': + case 'double': + case 'double precision': + case 'd_float': + $type[] = 'float'; + break; + case 'decimal': + case 'numeric': + $type[] = 'decimal'; + break; + case 'blob': + $type[] = ($field['field_sub_type'] == 'text') ? 'clob' : 'blob'; + $length = null; + break; + default: + throw new Doctrine_DataDict_Firebird_Exception('unknown database attribute type: '.$dbType); + } + + return array($type, $length, $unsigned, $fixed); + } + /** + * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $charset name of the charset + * @return string DBMS specific SQL code portion needed to set the CHARACTER SET + * of a field declaration. + */ + public function getCharsetFieldDeclaration($charset) + { + return 'CHARACTER SET '.$charset; + } + /** + * Obtain DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $collation name of the collation + * @return string DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration. + */ + public function getCollationFieldDeclaration($collation) + { + return 'COLLATE '.$collation; + } +} diff --git a/lib/Doctrine/DataDict/Mssql.php b/lib/Doctrine/DataDict/Mssql.php index e4720baef..cb860dd74 100644 --- a/lib/Doctrine/DataDict/Mssql.php +++ b/lib/Doctrine/DataDict/Mssql.php @@ -1,180 +1,180 @@ -. - */ -Doctrine::autoload('Doctrine_DataDict'); -/** - * @package Doctrine - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @author Konsta Vesterinen - * @author Lukas Smith (PEAR MDB2 library) - * @author Frank M. Kromann (PEAR MDB2 Mssql driver) - * @author David Coallier (PEAR MDB2 Mssql driver) - * @version $Revision$ - * @category Object Relational Mapping - * @link www.phpdoctrine.com - * @since 1.0 - */ -class Doctrine_DataDict_Mssql extends Doctrine_DataDict -{ - /** - * Obtain DBMS specific SQL code portion needed to declare an text type - * field to be used in statements like CREATE TABLE. - * - * @param array $field associative array with the name of the properties - * of the field being declared as array indexes. Currently, the types - * of supported field properties are as follows: - * - * length - * Integer value that determines the maximum length of the text - * field. If this argument is missing the field should be - * declared to have the longest length allowed by the DBMS. - * - * default - * Text value to be used as default for this field. - * - * notnull - * Boolean flag that indicates whether this field is constrained - * to not be set to null. - * - * @return string DBMS specific SQL code portion that should be used to - * declare the specified field. - */ - public function getNativeDeclaration($field) - { - switch ($field['type']) { - case 'array': - case 'object': - case 'text': - case 'char': - case 'varchar': - case 'string': - $length = !empty($field['length']) - ? $field['length'] : false; - - $fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false; - - return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')') - : ($length ? 'VARCHAR('.$length.')' : 'TEXT'); - case 'clob': - if (!empty($field['length'])) { - $length = $field['length']; - if ($length <= 8000) { - return 'VARCHAR('.$length.')'; - } - } - return 'TEXT'; - case 'blob': - if (!empty($field['length'])) { - $length = $field['length']; - if ($length <= 8000) { - return "VARBINARY($length)"; - } - } - return 'IMAGE'; - case 'integer': - case 'enum': - return 'INT'; - case 'boolean': - return 'BIT'; - case 'date': - return 'CHAR(' . strlen('YYYY-MM-DD') . ')'; - case 'time': - return 'CHAR(' . strlen('HH:MM:SS') . ')'; - case 'timestamp': - return 'CHAR(' . strlen('YYYY-MM-DD HH:MM:SS') . ')'; - case 'float': - return 'FLOAT'; - case 'decimal': - $length = !empty($field['length']) ? $field['length'] : 18; - return 'DECIMAL('.$length.','.$db->options['decimal_places'].')'; - } - return ''; - } - /** - * Maps a native array description of a field to a MDB2 datatype and length - * - * @param array $field native field description - * @return array containing the various possible types, length, sign, fixed - */ - public function getPortableDeclaration($field) - { - $db_type = preg_replace('/\d/','', strtolower($field['type']) ); - $length = (isset($field['length']) && $field['length'] > 0) ? $field['length'] : null; - - $type = array(); - // todo: unsigned handling seems to be missing - $unsigned = $fixed = null; - - if( ! isset($field['name'])) - $field['name'] = ''; - - switch ($db_type) { - case 'bit': - $type[0] = 'boolean'; - break; - case 'int': - $type[0] = 'integer'; - if($length == 1) { - $type[] = 'boolean'; - } - break; - case 'datetime': - $type[0] = 'timestamp'; - break; - case 'float': - case 'real': - case 'numeric': - $type[0] = 'float'; - break; - case 'decimal': - case 'money': - $type[0] = 'decimal'; - break; - case 'text': - case 'varchar': - $fixed = false; - case 'char': - $type[0] = 'string'; - if ($length == '1') { - $type[] = 'boolean'; - if (preg_match('/^[is|has]/', $field['name'])) { - $type = array_reverse($type); - } - } elseif (strstr($db_type, 'text')) { - $type[] = 'clob'; - } - if ($fixed !== false) { - $fixed = true; - } - break; - case 'image': - case 'varbinary': - $type[] = 'blob'; - $length = null; - break; - default: - throw new Doctrine_DataDict_Mssql_Exception('unknown database attribute type: '.$db_type); - } - - - - return array($type, $length, $unsigned, $fixed); - } -} +. + */ +Doctrine::autoload('Doctrine_DataDict'); +/** + * @package Doctrine + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @author Konsta Vesterinen + * @author Lukas Smith (PEAR MDB2 library) + * @author Frank M. Kromann (PEAR MDB2 Mssql driver) + * @author David Coallier (PEAR MDB2 Mssql driver) + * @version $Revision$ + * @category Object Relational Mapping + * @link www.phpdoctrine.com + * @since 1.0 + */ +class Doctrine_DataDict_Mssql extends Doctrine_DataDict +{ + /** + * Obtain DBMS specific SQL code portion needed to declare an text type + * field to be used in statements like CREATE TABLE. + * + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + */ + public function getNativeDeclaration($field) + { + switch ($field['type']) { + case 'array': + case 'object': + case 'text': + case 'char': + case 'varchar': + case 'string': + $length = !empty($field['length']) + ? $field['length'] : false; + + $fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false; + + return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')') + : ($length ? 'VARCHAR('.$length.')' : 'TEXT'); + case 'clob': + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 8000) { + return 'VARCHAR('.$length.')'; + } + } + return 'TEXT'; + case 'blob': + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 8000) { + return "VARBINARY($length)"; + } + } + return 'IMAGE'; + case 'integer': + case 'enum': + return 'INT'; + case 'boolean': + return 'BIT'; + case 'date': + return 'CHAR(' . strlen('YYYY-MM-DD') . ')'; + case 'time': + return 'CHAR(' . strlen('HH:MM:SS') . ')'; + case 'timestamp': + return 'CHAR(' . strlen('YYYY-MM-DD HH:MM:SS') . ')'; + case 'float': + return 'FLOAT'; + case 'decimal': + $length = !empty($field['length']) ? $field['length'] : 18; + return 'DECIMAL('.$length.','.$db->options['decimal_places'].')'; + } + return ''; + } + /** + * Maps a native array description of a field to a MDB2 datatype and length + * + * @param array $field native field description + * @return array containing the various possible types, length, sign, fixed + */ + public function getPortableDeclaration($field) + { + $db_type = preg_replace('/\d/','', strtolower($field['type']) ); + $length = (isset($field['length']) && $field['length'] > 0) ? $field['length'] : null; + + $type = array(); + // todo: unsigned handling seems to be missing + $unsigned = $fixed = null; + + if ( ! isset($field['name'])) + $field['name'] = ''; + + switch ($db_type) { + case 'bit': + $type[0] = 'boolean'; + break; + case 'int': + $type[0] = 'integer'; + if ($length == 1) { + $type[] = 'boolean'; + } + break; + case 'datetime': + $type[0] = 'timestamp'; + break; + case 'float': + case 'real': + case 'numeric': + $type[0] = 'float'; + break; + case 'decimal': + case 'money': + $type[0] = 'decimal'; + break; + case 'text': + case 'varchar': + $fixed = false; + case 'char': + $type[0] = 'string'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^[is|has]/', $field['name'])) { + $type = array_reverse($type); + } + } elseif (strstr($db_type, 'text')) { + $type[] = 'clob'; + } + if ($fixed !== false) { + $fixed = true; + } + break; + case 'image': + case 'varbinary': + $type[] = 'blob'; + $length = null; + break; + default: + throw new Doctrine_DataDict_Mssql_Exception('unknown database attribute type: '.$db_type); + } + + + + return array($type, $length, $unsigned, $fixed); + } +} diff --git a/lib/Doctrine/DataDict/Mysql.php b/lib/Doctrine/DataDict/Mysql.php index 4f067a70a..72653ceb9 100644 --- a/lib/Doctrine/DataDict/Mysql.php +++ b/lib/Doctrine/DataDict/Mysql.php @@ -1,439 +1,440 @@ -. - */ -Doctrine::autoload('Doctrine_DataDict'); -/** - * @package Doctrine - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @author Konsta Vesterinen - * @author Lukas Smith (PEAR MDB2 library) - * @version $Revision$ - * @category Object Relational Mapping - * @link www.phpdoctrine.com - * @since 1.0 - */ -class Doctrine_DataDict_Mysql extends Doctrine_DataDict -{ - protected $keywords = array( - 'ADD', 'ALL', 'ALTER', - 'ANALYZE', 'AND', 'AS', - 'ASC', 'ASENSITIVE', 'BEFORE', - 'BETWEEN', 'BIGINT', 'BINARY', - 'BLOB', 'BOTH', 'BY', - 'CALL', 'CASCADE', 'CASE', - 'CHANGE', 'CHAR', 'CHARACTER', - 'CHECK', 'COLLATE', 'COLUMN', - 'CONDITION', 'CONNECTION', 'CONSTRAINT', - 'CONTINUE', 'CONVERT', 'CREATE', - 'CROSS', 'CURRENT_DATE', 'CURRENT_TIME', - 'CURRENT_TIMESTAMP', 'CURRENT_USER', 'CURSOR', - 'DATABASE', 'DATABASES', 'DAY_HOUR', - 'DAY_MICROSECOND', 'DAY_MINUTE', 'DAY_SECOND', - 'DEC', 'DECIMAL', 'DECLARE', - 'DEFAULT', 'DELAYED', 'DELETE', - 'DESC', 'DESCRIBE', 'DETERMINISTIC', - 'DISTINCT', 'DISTINCTROW', 'DIV', - 'DOUBLE', 'DROP', 'DUAL', - 'EACH', 'ELSE', 'ELSEIF', - 'ENCLOSED', 'ESCAPED', 'EXISTS', - 'EXIT', 'EXPLAIN', 'FALSE', - 'FETCH', 'FLOAT', 'FLOAT4', - 'FLOAT8', 'FOR', 'FORCE', - 'FOREIGN', 'FROM', 'FULLTEXT', - 'GRANT', 'GROUP', 'HAVING', - 'HIGH_PRIORITY', 'HOUR_MICROSECOND', 'HOUR_MINUTE', - 'HOUR_SECOND', 'IF', 'IGNORE', - 'IN', 'INDEX', 'INFILE', - 'INNER', 'INOUT', 'INSENSITIVE', - 'INSERT', 'INT', 'INT1', - 'INT2', 'INT3', 'INT4', - 'INT8', 'INTEGER', 'INTERVAL', - 'INTO', 'IS', 'ITERATE', - 'JOIN', 'KEY', 'KEYS', - 'KILL', 'LEADING', 'LEAVE', - 'LEFT', 'LIKE', 'LIMIT', - 'LINES', 'LOAD', 'LOCALTIME', - 'LOCALTIMESTAMP', 'LOCK', 'LONG', - 'LONGBLOB', 'LONGTEXT', 'LOOP', - 'LOW_PRIORITY', 'MATCH', 'MEDIUMBLOB', - 'MEDIUMINT', 'MEDIUMTEXT', 'MIDDLEINT', - 'MINUTE_MICROSECOND', 'MINUTE_SECOND', 'MOD', - 'MODIFIES', 'NATURAL', 'NOT', - 'NO_WRITE_TO_BINLOG', 'NULL', 'NUMERIC', - 'ON', 'OPTIMIZE', 'OPTION', - 'OPTIONALLY', 'OR', 'ORDER', - 'OUT', 'OUTER', 'OUTFILE', - 'PRECISION', 'PRIMARY', 'PROCEDURE', - 'PURGE', 'RAID0', 'READ', - 'READS', 'REAL', 'REFERENCES', - 'REGEXP', 'RELEASE', 'RENAME', - 'REPEAT', 'REPLACE', 'REQUIRE', - 'RESTRICT', 'RETURN', 'REVOKE', - 'RIGHT', 'RLIKE', 'SCHEMA', - 'SCHEMAS', 'SECOND_MICROSECOND', 'SELECT', - 'SENSITIVE', 'SEPARATOR', 'SET', - 'SHOW', 'SMALLINT', 'SONAME', - 'SPATIAL', 'SPECIFIC', 'SQL', - 'SQLEXCEPTION', 'SQLSTATE', 'SQLWARNING', - 'SQL_BIG_RESULT', 'SQL_CALC_FOUND_ROWS', 'SQL_SMALL_RESULT', - 'SSL', 'STARTING', 'STRAIGHT_JOIN', - 'TABLE', 'TERMINATED', 'THEN', - 'TINYBLOB', 'TINYINT', 'TINYTEXT', - 'TO', 'TRAILING', 'TRIGGER', - 'TRUE', 'UNDO', 'UNION', - 'UNIQUE', 'UNLOCK', 'UNSIGNED', - 'UPDATE', 'USAGE', 'USE', - 'USING', 'UTC_DATE', 'UTC_TIME', - 'UTC_TIMESTAMP', 'VALUES', 'VARBINARY', - 'VARCHAR', 'VARCHARACTER', 'VARYING', - 'WHEN', 'WHERE', 'WHILE', - 'WITH', 'WRITE', 'X509', - 'XOR', 'YEAR_MONTH', 'ZEROFILL' - ); - - /** - * Obtain DBMS specific SQL code portion needed to declare an text type - * field to be used in statements like CREATE TABLE. - * - * @param array $field associative array with the name of the properties - * of the field being declared as array indexes. Currently, the types - * of supported field properties are as follows: - * - * length - * Integer value that determines the maximum length of the text - * field. If this argument is missing the field should be - * declared to have the longest length allowed by the DBMS. - * - * default - * Text value to be used as default for this field. - * - * notnull - * Boolean flag that indicates whether this field is constrained - * to not be set to null. - * - * @return string DBMS specific SQL code portion that should be used to - * declare the specified field. - */ - public function getNativeDeclaration($field) - { - switch ($field['type']) { - case 'char': - $length = (! empty($field['length'])) ? $field['length'] : false; - - return $length ? 'CHAR('.$length.')' : 'CHAR(255)'; - case 'varchar': - case 'array': - case 'object': - case 'string': - - if ( ! isset($field['length'])) { - if (array_key_exists('default', $field)) { - $field['length'] = $this->conn->varchar_max_length; - } else { - $field['length'] = false; - } - } - - $length = ($field['length'] < $this->conn->varchar_max_length) ? $field['length'] : false; - $fixed = (isset($field['fixed'])) ? $field['fixed'] : false; - - return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR(255)') - : ($length ? 'VARCHAR(' . $length . ')' : 'TEXT'); - case 'clob': - if (!empty($field['length'])) { - $length = $field['length']; - if ($length <= 255) { - return 'TINYTEXT'; - } elseif ($length <= 65532) { - return 'TEXT'; - } elseif ($length <= 16777215) { - return 'MEDIUMTEXT'; - } - } - return 'LONGTEXT'; - case 'blob': - if (!empty($field['length'])) { - $length = $field['length']; - if ($length <= 255) { - return 'TINYBLOB'; - } elseif ($length <= 65532) { - return 'BLOB'; - } elseif ($length <= 16777215) { - return 'MEDIUMBLOB'; - } - } - return 'LONGBLOB'; - case 'integer': - case 'enum': - if (!empty($field['length'])) { - $length = $field['length']; - if ($length <= 1) { - return 'TINYINT'; - } elseif ($length == 2) { - return 'SMALLINT'; - } elseif ($length == 3) { - return 'MEDIUMINT'; - } elseif ($length == 4) { - return 'INT'; - } elseif ($length > 4) { - return 'BIGINT'; - } - } - return 'INT'; - case 'boolean': - return 'TINYINT(1)'; - case 'date': - return 'DATE'; - case 'time': - return 'TIME'; - case 'timestamp': - return 'DATETIME'; - case 'float': - return 'DOUBLE'; - case 'decimal': - $length = !empty($field['length']) ? $field['length'] : 18; - return 'DECIMAL(' . $length . ',' . 0 . ')'; //$this->dbh->options['decimal_places'] . ')'; - } - return ''; - } - /** - * Maps a native array description of a field to a MDB2 datatype and length - * - * @param array $field native field description - * @return array containing the various possible types, length, sign, fixed - */ - public function getPortableDeclaration(array $field) - { - $dbType = strtolower($field['type']); - $dbType = strtok($dbType, '(), '); - if ($dbType == 'national') { - $dbType = strtok('(), '); - } - if (isset($field['length'])) { - $length = $field['length']; - $decimal = ''; - } else { - $length = strtok('(), '); - $decimal = strtok('(), '); - } - $type = array(); - $unsigned = $fixed = null; - - if( ! isset($field['name'])) - $field['name'] = ''; - - switch ($dbType) { - case 'tinyint': - $type[] = 'integer'; - $type[] = 'boolean'; - if (preg_match('/^(is|has)/', $field['name'])) { - $type = array_reverse($type); - } - $unsigned = preg_match('/ unsigned/i', $field['type']); - $length = 1; - break; - case 'smallint': - $type[] = 'integer'; - $unsigned = preg_match('/ unsigned/i', $field['type']); - $length = 2; - break; - case 'mediumint': - $type[] = 'integer'; - $unsigned = preg_match('/ unsigned/i', $field['type']); - $length = 3; - break; - case 'int': - case 'integer': - $type[] = 'integer'; - $unsigned = preg_match('/ unsigned/i', $field['type']); - $length = 4; - break; - case 'bigint': - $type[] = 'integer'; - $unsigned = preg_match('/ unsigned/i', $field['type']); - $length = 8; - break; - case 'tinytext': - case 'mediumtext': - case 'longtext': - case 'text': - case 'text': - case 'varchar': - $fixed = false; - case 'string': - case 'char': - $type[] = 'string'; - if ($length == '1') { - $type[] = 'boolean'; - if (preg_match('/^(is|has)/', $field['name'])) { - $type = array_reverse($type); - } - } elseif (strstr($dbType, 'text')) { - $type[] = 'clob'; - if ($decimal == 'binary') { - $type[] = 'blob'; - } - } - if ($fixed !== false) { - $fixed = true; - } - break; - case 'enum': - $type[] = 'text'; - preg_match_all('/\'.+\'/U', $field['type'], $matches); - $length = 0; - $fixed = false; - if (is_array($matches)) { - foreach ($matches[0] as $value) { - $length = max($length, strlen($value)-2); - } - if ($length == '1' && count($matches[0]) == 2) { - $type[] = 'boolean'; - if (preg_match('/^(is|has)/', $field['name'])) { - $type = array_reverse($type); - } - } - } - $type[] = 'integer'; - case 'set': - $fixed = false; - $type[] = 'text'; - $type[] = 'integer'; - break; - case 'date': - $type[] = 'date'; - $length = null; - break; - case 'datetime': - case 'timestamp': - $type[] = 'timestamp'; - $length = null; - break; - case 'time': - $type[] = 'time'; - $length = null; - break; - case 'float': - case 'double': - case 'real': - $type[] = 'float'; - $unsigned = preg_match('/ unsigned/i', $field['type']); - break; - case 'unknown': - case 'decimal': - case 'numeric': - $type[] = 'decimal'; - $unsigned = preg_match('/ unsigned/i', $field['type']); - break; - case 'tinyblob': - case 'mediumblob': - case 'longblob': - case 'blob': - $type[] = 'blob'; - $length = null; - break; - case 'year': - $type[] = 'integer'; - $type[] = 'date'; - $length = null; - break; - default: - throw new Doctrine_DataDict_Mysql_Exception('unknown database attribute type: '.$dbType); - } - - $length = ((int) $length == 0) ? null : (int) $length; - - - return array($type, $length, $unsigned, $fixed); - } - /** - * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET - * of a field declaration to be used in statements like CREATE TABLE. - * - * @param string $charset name of the charset - * @return string DBMS specific SQL code portion needed to set the CHARACTER SET - * of a field declaration. - */ - public function getCharsetFieldDeclaration($charset) - { - return 'CHARACTER SET '.$charset; - } - /** - * Obtain DBMS specific SQL code portion needed to set the COLLATION - * of a field declaration to be used in statements like CREATE TABLE. - * - * @param string $collation name of the collation - * @return string DBMS specific SQL code portion needed to set the COLLATION - * of a field declaration. - */ - public function getCollationFieldDeclaration($collation) - { - return 'COLLATE '.$collation; - } - /** - * Obtain DBMS specific SQL code portion needed to declare an integer type - * field to be used in statements like CREATE TABLE. - * - * @param string $name name the field to be declared. - * @param string $field associative array with the name of the properties - * of the field being declared as array indexes. - * Currently, the types of supported field - * properties are as follows: - * - * unsigned - * Boolean flag that indicates whether the field - * should be declared as unsigned integer if - * possible. - * - * default - * Integer value to be used as default for this - * field. - * - * notnull - * Boolean flag that indicates whether this field is - * constrained to not be set to null. - * @return string DBMS specific SQL code portion that should be used to - * declare the specified field. - */ - public function getIntegerDeclaration($name, $field) - { - $default = $autoinc = ''; - if (!empty($field['autoincrement'])) { - $autoinc = ' AUTO_INCREMENT PRIMARY KEY'; - } elseif (array_key_exists('default', $field)) { - if ($field['default'] === '') { - $field['default'] = empty($field['notnull']) ? null : 0; - } - $default = ' DEFAULT '.$this->conn->getDbh()->quote($field['default']); - } - /** - elseif (empty($field['notnull'])) { - $default = ' DEFAULT NULL'; - } - */ - - $notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : ''; - $unsigned = (isset($field['unsigned']) && $field['unsigned']) ? ' UNSIGNED' : ''; - - $name = $this->conn->quoteIdentifier($name, true); - - return $name . ' ' . $this->getNativeDeclaration($field) . $unsigned . $default . $notnull . $autoinc; - } -} +. + */ +Doctrine::autoload('Doctrine_DataDict'); +/** + * @package Doctrine + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @author Konsta Vesterinen + * @author Lukas Smith (PEAR MDB2 library) + * @version $Revision$ + * @category Object Relational Mapping + * @link www.phpdoctrine.com + * @since 1.0 + */ +class Doctrine_DataDict_Mysql extends Doctrine_DataDict +{ + protected $keywords = array( + 'ADD', 'ALL', 'ALTER', + 'ANALYZE', 'AND', 'AS', + 'ASC', 'ASENSITIVE', 'BEFORE', + 'BETWEEN', 'BIGINT', 'BINARY', + 'BLOB', 'BOTH', 'BY', + 'CALL', 'CASCADE', 'CASE', + 'CHANGE', 'CHAR', 'CHARACTER', + 'CHECK', 'COLLATE', 'COLUMN', + 'CONDITION', 'CONNECTION', 'CONSTRAINT', + 'CONTINUE', 'CONVERT', 'CREATE', + 'CROSS', 'CURRENT_DATE', 'CURRENT_TIME', + 'CURRENT_TIMESTAMP', 'CURRENT_USER', 'CURSOR', + 'DATABASE', 'DATABASES', 'DAY_HOUR', + 'DAY_MICROSECOND', 'DAY_MINUTE', 'DAY_SECOND', + 'DEC', 'DECIMAL', 'DECLARE', + 'DEFAULT', 'DELAYED', 'DELETE', + 'DESC', 'DESCRIBE', 'DETERMINISTIC', + 'DISTINCT', 'DISTINCTROW', 'DIV', + 'DOUBLE', 'DROP', 'DUAL', + 'EACH', 'ELSE', 'ELSEIF', + 'ENCLOSED', 'ESCAPED', 'EXISTS', + 'EXIT', 'EXPLAIN', 'FALSE', + 'FETCH', 'FLOAT', 'FLOAT4', + 'FLOAT8', 'FOR', 'FORCE', + 'FOREIGN', 'FROM', 'FULLTEXT', + 'GRANT', 'GROUP', 'HAVING', + 'HIGH_PRIORITY', 'HOUR_MICROSECOND', 'HOUR_MINUTE', + 'HOUR_SECOND', 'IF', 'IGNORE', + 'IN', 'INDEX', 'INFILE', + 'INNER', 'INOUT', 'INSENSITIVE', + 'INSERT', 'INT', 'INT1', + 'INT2', 'INT3', 'INT4', + 'INT8', 'INTEGER', 'INTERVAL', + 'INTO', 'IS', 'ITERATE', + 'JOIN', 'KEY', 'KEYS', + 'KILL', 'LEADING', 'LEAVE', + 'LEFT', 'LIKE', 'LIMIT', + 'LINES', 'LOAD', 'LOCALTIME', + 'LOCALTIMESTAMP', 'LOCK', 'LONG', + 'LONGBLOB', 'LONGTEXT', 'LOOP', + 'LOW_PRIORITY', 'MATCH', 'MEDIUMBLOB', + 'MEDIUMINT', 'MEDIUMTEXT', 'MIDDLEINT', + 'MINUTE_MICROSECOND', 'MINUTE_SECOND', 'MOD', + 'MODIFIES', 'NATURAL', 'NOT', + 'NO_WRITE_TO_BINLOG', 'NULL', 'NUMERIC', + 'ON', 'OPTIMIZE', 'OPTION', + 'OPTIONALLY', 'OR', 'ORDER', + 'OUT', 'OUTER', 'OUTFILE', + 'PRECISION', 'PRIMARY', 'PROCEDURE', + 'PURGE', 'RAID0', 'READ', + 'READS', 'REAL', 'REFERENCES', + 'REGEXP', 'RELEASE', 'RENAME', + 'REPEAT', 'REPLACE', 'REQUIRE', + 'RESTRICT', 'RETURN', 'REVOKE', + 'RIGHT', 'RLIKE', 'SCHEMA', + 'SCHEMAS', 'SECOND_MICROSECOND', 'SELECT', + 'SENSITIVE', 'SEPARATOR', 'SET', + 'SHOW', 'SMALLINT', 'SONAME', + 'SPATIAL', 'SPECIFIC', 'SQL', + 'SQLEXCEPTION', 'SQLSTATE', 'SQLWARNING', + 'SQL_BIG_RESULT', 'SQL_CALC_FOUND_ROWS', 'SQL_SMALL_RESULT', + 'SSL', 'STARTING', 'STRAIGHT_JOIN', + 'TABLE', 'TERMINATED', 'THEN', + 'TINYBLOB', 'TINYINT', 'TINYTEXT', + 'TO', 'TRAILING', 'TRIGGER', + 'TRUE', 'UNDO', 'UNION', + 'UNIQUE', 'UNLOCK', 'UNSIGNED', + 'UPDATE', 'USAGE', 'USE', + 'USING', 'UTC_DATE', 'UTC_TIME', + 'UTC_TIMESTAMP', 'VALUES', 'VARBINARY', + 'VARCHAR', 'VARCHARACTER', 'VARYING', + 'WHEN', 'WHERE', 'WHILE', + 'WITH', 'WRITE', 'X509', + 'XOR', 'YEAR_MONTH', 'ZEROFILL' + ); + + /** + * Obtain DBMS specific SQL code portion needed to declare an text type + * field to be used in statements like CREATE TABLE. + * + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + */ + public function getNativeDeclaration($field) + { + switch ($field['type']) { + case 'char': + $length = (! empty($field['length'])) ? $field['length'] : false; + + return $length ? 'CHAR('.$length.')' : 'CHAR(255)'; + case 'varchar': + case 'array': + case 'object': + case 'string': + + if ( ! isset($field['length'])) { + if (array_key_exists('default', $field)) { + $field['length'] = $this->conn->varchar_max_length; + } else { + $field['length'] = false; + } + } + + $length = ($field['length'] < $this->conn->varchar_max_length) ? $field['length'] : false; + $fixed = (isset($field['fixed'])) ? $field['fixed'] : false; + + return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR(255)') + : ($length ? 'VARCHAR(' . $length . ')' : 'TEXT'); + case 'clob': + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 255) { + return 'TINYTEXT'; + } elseif ($length <= 65532) { + return 'TEXT'; + } elseif ($length <= 16777215) { + return 'MEDIUMTEXT'; + } + } + return 'LONGTEXT'; + case 'blob': + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 255) { + return 'TINYBLOB'; + } elseif ($length <= 65532) { + return 'BLOB'; + } elseif ($length <= 16777215) { + return 'MEDIUMBLOB'; + } + } + return 'LONGBLOB'; + case 'integer': + case 'enum': + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 1) { + return 'TINYINT'; + } elseif ($length == 2) { + return 'SMALLINT'; + } elseif ($length == 3) { + return 'MEDIUMINT'; + } elseif ($length == 4) { + return 'INT'; + } elseif ($length > 4) { + return 'BIGINT'; + } + } + return 'INT'; + case 'boolean': + return 'TINYINT(1)'; + case 'date': + return 'DATE'; + case 'time': + return 'TIME'; + case 'timestamp': + return 'DATETIME'; + case 'float': + return 'DOUBLE'; + case 'decimal': + $length = !empty($field['length']) ? $field['length'] : 18; + return 'DECIMAL(' . $length . ',' . 0 . ')'; //$this->dbh->options['decimal_places'] . ')'; + } + return ''; + } + /** + * Maps a native array description of a field to a MDB2 datatype and length + * + * @param array $field native field description + * @return array containing the various possible types, length, sign, fixed + */ + public function getPortableDeclaration(array $field) + { + $dbType = strtolower($field['type']); + $dbType = strtok($dbType, '(), '); + if ($dbType == 'national') { + $dbType = strtok('(), '); + } + if (isset($field['length'])) { + $length = $field['length']; + $decimal = ''; + } else { + $length = strtok('(), '); + $decimal = strtok('(), '); + } + $type = array(); + $unsigned = $fixed = null; + + if ( ! isset($field['name'])) { + $field['name'] = ''; + } + + switch ($dbType) { + case 'tinyint': + $type[] = 'integer'; + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 1; + break; + case 'smallint': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 2; + break; + case 'mediumint': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 3; + break; + case 'int': + case 'integer': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 4; + break; + case 'bigint': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 8; + break; + case 'tinytext': + case 'mediumtext': + case 'longtext': + case 'text': + case 'text': + case 'varchar': + $fixed = false; + case 'string': + case 'char': + $type[] = 'string'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } elseif (strstr($dbType, 'text')) { + $type[] = 'clob'; + if ($decimal == 'binary') { + $type[] = 'blob'; + } + } + if ($fixed !== false) { + $fixed = true; + } + break; + case 'enum': + $type[] = 'text'; + preg_match_all('/\'.+\'/U', $field['type'], $matches); + $length = 0; + $fixed = false; + if (is_array($matches)) { + foreach ($matches[0] as $value) { + $length = max($length, strlen($value)-2); + } + if ($length == '1' && count($matches[0]) == 2) { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } + } + $type[] = 'integer'; + case 'set': + $fixed = false; + $type[] = 'text'; + $type[] = 'integer'; + break; + case 'date': + $type[] = 'date'; + $length = null; + break; + case 'datetime': + case 'timestamp': + $type[] = 'timestamp'; + $length = null; + break; + case 'time': + $type[] = 'time'; + $length = null; + break; + case 'float': + case 'double': + case 'real': + $type[] = 'float'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + break; + case 'unknown': + case 'decimal': + case 'numeric': + $type[] = 'decimal'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + break; + case 'tinyblob': + case 'mediumblob': + case 'longblob': + case 'blob': + $type[] = 'blob'; + $length = null; + break; + case 'year': + $type[] = 'integer'; + $type[] = 'date'; + $length = null; + break; + default: + throw new Doctrine_DataDict_Mysql_Exception('unknown database attribute type: '.$dbType); + } + + $length = ((int) $length == 0) ? null : (int) $length; + + + return array($type, $length, $unsigned, $fixed); + } + /** + * Obtain DBMS specific SQL code portion needed to set the CHARACTER SET + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $charset name of the charset + * @return string DBMS specific SQL code portion needed to set the CHARACTER SET + * of a field declaration. + */ + public function getCharsetFieldDeclaration($charset) + { + return 'CHARACTER SET '.$charset; + } + /** + * Obtain DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration to be used in statements like CREATE TABLE. + * + * @param string $collation name of the collation + * @return string DBMS specific SQL code portion needed to set the COLLATION + * of a field declaration. + */ + public function getCollationFieldDeclaration($collation) + { + return 'COLLATE '.$collation; + } + /** + * Obtain DBMS specific SQL code portion needed to declare an integer type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param string $field associative array with the name of the properties + * of the field being declared as array indexes. + * Currently, the types of supported field + * properties are as follows: + * + * unsigned + * Boolean flag that indicates whether the field + * should be declared as unsigned integer if + * possible. + * + * default + * Integer value to be used as default for this + * field. + * + * notnull + * Boolean flag that indicates whether this field is + * constrained to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + */ + public function getIntegerDeclaration($name, $field) + { + $default = $autoinc = ''; + if (!empty($field['autoincrement'])) { + $autoinc = ' AUTO_INCREMENT PRIMARY KEY'; + } elseif (array_key_exists('default', $field)) { + if ($field['default'] === '') { + $field['default'] = empty($field['notnull']) ? null : 0; + } + $default = ' DEFAULT '.$this->conn->getDbh()->quote($field['default']); + } + /** + elseif (empty($field['notnull'])) { + $default = ' DEFAULT NULL'; + } + */ + + $notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : ''; + $unsigned = (isset($field['unsigned']) && $field['unsigned']) ? ' UNSIGNED' : ''; + + $name = $this->conn->quoteIdentifier($name, true); + + return $name . ' ' . $this->getNativeDeclaration($field) . $unsigned . $default . $notnull . $autoinc; + } +} diff --git a/lib/Doctrine/DataDict/Oracle.php b/lib/Doctrine/DataDict/Oracle.php index fa18ba297..bd0dfef9f 100644 --- a/lib/Doctrine/DataDict/Oracle.php +++ b/lib/Doctrine/DataDict/Oracle.php @@ -1,181 +1,182 @@ -. - */ -/** - * @package Doctrine - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @author Konsta Vesterinen - * @version $Revision$ - * @category Object Relational Mapping - * @link www.phpdoctrine.com - * @since 1.0 - */ -class Doctrine_DataDict_Oracle extends Doctrine_DataDict -{ - /** - * Obtain DBMS specific SQL code portion needed to declare an text type - * field to be used in statements like CREATE TABLE. - * - * @param array $field associative array with the name of the properties - * of the field being declared as array indexes. Currently, the types - * of supported field properties are as follows: - * - * length - * Integer value that determines the maximum length of the text - * field. If this argument is missing the field should be - * declared to have the longest length allowed by the DBMS. - * - * default - * Text value to be used as default for this field. - * - * notnull - * Boolean flag that indicates whether this field is constrained - * to not be set to null. - * @return string DBMS specific SQL code portion that should be used to - * declare the specified field. - */ - public function getNativeDeclaration(array $field) - { - switch ($field['type']) { - case 'string': - case 'array': - case 'object': - case 'gzip': - case 'char': - case 'varchar': - $length = !empty($field['length']) - ? $field['length'] : 16777215; // TODO: $db->options['default_text_field_length']; - - $fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false; - - return $fixed ? 'CHAR('.$length.')' : 'VARCHAR2('.$length.')'; - case 'clob': - return 'CLOB'; - case 'blob': - return 'BLOB'; - case 'integer': - case 'enum': - if (!empty($field['length'])) { - return 'NUMBER('.$field['length'].')'; - } - return 'INT'; - case 'boolean': - return 'NUMBER(1)'; - case 'date': - case 'time': - case 'timestamp': - return 'DATE'; - case 'float': - return 'NUMBER'; - case 'decimal': - return 'NUMBER(*,'.$db->options['decimal_places'].')'; - } - } - /** - * Maps a native array description of a field to a doctrine datatype and length - * - * @param array $field native field description - * @return array containing the various possible types, length, sign, fixed - * @throws Doctrine_DataDict_Oracle_Exception - */ - public function getPortableDeclaration(array $field) - { - $db_type = strtolower($field['type']); - $type = array(); - $length = $unsigned = $fixed = null; - if (!empty($field['length'])) { - $length = $field['length']; - } - - if( ! isset($field['name'])) - $field['name'] = ''; - - switch ($db_type) { - case 'integer': - case 'pls_integer': - case 'binary_integer': - $type[] = 'integer'; - if ($length == '1') { - $type[] = 'boolean'; - if (preg_match('/^(is|has)/', $field['name'])) { - $type = array_reverse($type); - } - } - break; - case 'varchar': - case 'varchar2': - case 'nvarchar2': - $fixed = false; - case 'char': - case 'nchar': - $type[] = 'string'; - if ($length == '1') { - $type[] = 'boolean'; - if (preg_match('/^(is|has)/', $field['name'])) { - $type = array_reverse($type); - } - } - if ($fixed !== false) { - $fixed = true; - } - break; - case 'date': - case 'timestamp': - $type[] = 'timestamp'; - $length = null; - break; - case 'float': - $type[] = 'float'; - break; - case 'number': - if (!empty($field['scale'])) { - $type[] = 'decimal'; - } else { - $type[] = 'integer'; - if ($length == '1') { - $type[] = 'boolean'; - if (preg_match('/^(is|has)/', $field['name'])) { - $type = array_reverse($type); - } - } - } - break; - case 'long': - $type[] = 'string'; - case 'clob': - case 'nclob': - $type[] = 'clob'; - break; - case 'blob': - case 'raw': - case 'long raw': - case 'bfile': - $type[] = 'blob'; - $length = null; - break; - case 'rowid': - case 'urowid': - default: - throw new Doctrine_DataDict_Oracle_Exception('unknown database attribute type: '.$db_type); - } - - return array($type, $length, $unsigned, $fixed); - } -} +. + */ +/** + * @package Doctrine + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @author Konsta Vesterinen + * @version $Revision$ + * @category Object Relational Mapping + * @link www.phpdoctrine.com + * @since 1.0 + */ +class Doctrine_DataDict_Oracle extends Doctrine_DataDict +{ + /** + * Obtain DBMS specific SQL code portion needed to declare an text type + * field to be used in statements like CREATE TABLE. + * + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + */ + public function getNativeDeclaration(array $field) + { + switch ($field['type']) { + case 'string': + case 'array': + case 'object': + case 'gzip': + case 'char': + case 'varchar': + $length = !empty($field['length']) + ? $field['length'] : 16777215; // TODO: $db->options['default_text_field_length']; + + $fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false; + + return $fixed ? 'CHAR('.$length.')' : 'VARCHAR2('.$length.')'; + case 'clob': + return 'CLOB'; + case 'blob': + return 'BLOB'; + case 'integer': + case 'enum': + if (!empty($field['length'])) { + return 'NUMBER('.$field['length'].')'; + } + return 'INT'; + case 'boolean': + return 'NUMBER(1)'; + case 'date': + case 'time': + case 'timestamp': + return 'DATE'; + case 'float': + return 'NUMBER'; + case 'decimal': + return 'NUMBER(*,'.$db->options['decimal_places'].')'; + } + } + /** + * Maps a native array description of a field to a doctrine datatype and length + * + * @param array $field native field description + * @return array containing the various possible types, length, sign, fixed + * @throws Doctrine_DataDict_Oracle_Exception + */ + public function getPortableDeclaration(array $field) + { + $db_type = strtolower($field['type']); + $type = array(); + $length = $unsigned = $fixed = null; + if (!empty($field['length'])) { + $length = $field['length']; + } + + if ( ! isset($field['name'])) { + $field['name'] = ''; + } + + switch ($db_type) { + case 'integer': + case 'pls_integer': + case 'binary_integer': + $type[] = 'integer'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } + break; + case 'varchar': + case 'varchar2': + case 'nvarchar2': + $fixed = false; + case 'char': + case 'nchar': + $type[] = 'string'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } + if ($fixed !== false) { + $fixed = true; + } + break; + case 'date': + case 'timestamp': + $type[] = 'timestamp'; + $length = null; + break; + case 'float': + $type[] = 'float'; + break; + case 'number': + if (!empty($field['scale'])) { + $type[] = 'decimal'; + } else { + $type[] = 'integer'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } + } + break; + case 'long': + $type[] = 'string'; + case 'clob': + case 'nclob': + $type[] = 'clob'; + break; + case 'blob': + case 'raw': + case 'long raw': + case 'bfile': + $type[] = 'blob'; + $length = null; + break; + case 'rowid': + case 'urowid': + default: + throw new Doctrine_DataDict_Oracle_Exception('unknown database attribute type: '.$db_type); + } + + return array($type, $length, $unsigned, $fixed); + } +} diff --git a/lib/Doctrine/DataDict/Pgsql.php b/lib/Doctrine/DataDict/Pgsql.php index 67ec1d801..3f51666bd 100644 --- a/lib/Doctrine/DataDict/Pgsql.php +++ b/lib/Doctrine/DataDict/Pgsql.php @@ -1,597 +1,598 @@ -. - */ -/** - * @package Doctrine - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @author Konsta Vesterinen - * @author Paul Cooper - * @author Lukas Smith (PEAR MDB2 library) - * @version $Revision$ - * @category Object Relational Mapping - * @link www.phpdoctrine.com - * @since 1.0 - */ -class Doctrine_DataDict_Pgsql extends Doctrine_DataDict -{ - /** - * @param array $reservedKeyWords an array of reserved keywords by pgsql - */ - protected static $reservedKeyWords = array( - 'abort', - 'absolute', - 'access', - 'action', - 'add', - 'after', - 'aggregate', - 'all', - 'alter', - 'analyse', - 'analyze', - 'and', - 'any', - 'as', - 'asc', - 'assertion', - 'assignment', - 'at', - 'authorization', - 'backward', - 'before', - 'begin', - 'between', - 'bigint', - 'binary', - 'bit', - 'boolean', - 'both', - 'by', - 'cache', - 'called', - 'cascade', - 'case', - 'cast', - 'chain', - 'char', - 'character', - 'characteristics', - 'check', - 'checkpoint', - 'class', - 'close', - 'cluster', - 'coalesce', - 'collate', - 'column', - 'comment', - 'commit', - 'committed', - 'constraint', - 'constraints', - 'conversion', - 'convert', - 'copy', - 'create', - 'createdb', - 'createuser', - 'cross', - 'current_date', - 'current_time', - 'current_timestamp', - 'current_user', - 'cursor', - 'cycle', - 'database', - 'day', - 'deallocate', - 'dec', - 'decimal', - 'declare', - 'default', - 'deferrable', - 'deferred', - 'definer', - 'delete', - 'delimiter', - 'delimiters', - 'desc', - 'distinct', - 'do', - 'domain', - 'double', - 'drop', - 'each', - 'else', - 'encoding', - 'encrypted', - 'end', - 'escape', - 'except', - 'exclusive', - 'execute', - 'exists', - 'explain', - 'external', - 'extract', - 'false', - 'fetch', - 'float', - 'for', - 'force', - 'foreign', - 'forward', - 'freeze', - 'from', - 'full', - 'function', - 'get', - 'global', - 'grant', - 'group', - 'handler', - 'having', - 'hour', - 'ilike', - 'immediate', - 'immutable', - 'implicit', - 'in', - 'increment', - 'index', - 'inherits', - 'initially', - 'inner', - 'inout', - 'input', - 'insensitive', - 'insert', - 'instead', - 'int', - 'integer', - 'intersect', - 'interval', - 'into', - 'invoker', - 'is', - 'isnull', - 'isolation', - 'join', - 'key', - 'lancompiler', - 'language', - 'leading', - 'left', - 'level', - 'like', - 'limit', - 'listen', - 'load', - 'local', - 'localtime', - 'localtimestamp', - 'location', - 'lock', - 'match', - 'maxvalue', - 'minute', - 'minvalue', - 'mode', - 'month', - 'move', - 'names', - 'national', - 'natural', - 'nchar', - 'new', - 'next', - 'no', - 'nocreatedb', - 'nocreateuser', - 'none', - 'not', - 'nothing', - 'notify', - 'notnull', - 'null', - 'nullif', - 'numeric', - 'of', - 'off', - 'offset', - 'oids', - 'old', - 'on', - 'only', - 'operator', - 'option', - 'or', - 'order', - 'out', - 'outer', - 'overlaps', - 'overlay', - 'owner', - 'partial', - 'password', - 'path', - 'pendant', - 'placing', - 'position', - 'precision', - 'prepare', - 'primary', - 'prior', - 'privileges', - 'procedural', - 'procedure', - 'read', - 'real', - 'recheck', - 'references', - 'reindex', - 'relative', - 'rename', - 'replace', - 'reset', - 'restrict', - 'returns', - 'revoke', - 'right', - 'rollback', - 'row', - 'rule', - 'schema', - 'scroll', - 'second', - 'security', - 'select', - 'sequence', - 'serializable', - 'session', - 'session_user', - 'set', - 'setof', - 'share', - 'show', - 'similar', - 'simple', - 'smallint', - 'some', - 'stable', - 'start', - 'statement', - 'statistics', - 'stdin', - 'stdout', - 'storage', - 'strict', - 'substring', - 'sysid', - 'table', - 'temp', - 'template', - 'temporary', - 'then', - 'time', - 'timestamp', - 'to', - 'toast', - 'trailing', - 'transaction', - 'treat', - 'trigger', - 'trim', - 'true', - 'truncate', - 'trusted', - 'type', - 'unencrypted', - 'union', - 'unique', - 'unknown', - 'unlisten', - 'until', - 'update', - 'usage', - 'user', - 'using', - 'vacuum', - 'valid', - 'validator', - 'values', - 'varchar', - 'varying', - 'verbose', - 'version', - 'view', - 'volatile', - 'when', - 'where', - 'with', - 'without', - 'work', - 'write', - 'year', - 'zone' - ); - - /** - * Obtain DBMS specific SQL code portion needed to declare an text type - * field to be used in statements like CREATE TABLE. - * - * @param array $field associative array with the name of the properties - * of the field being declared as array indexes. Currently, the types - * of supported field properties are as follows: - * - * length - * Integer value that determines the maximum length of the text - * field. If this argument is missing the field should be - * declared to have the longest length allowed by the DBMS. - * - * default - * Text value to be used as default for this field. - * - * notnull - * Boolean flag that indicates whether this field is constrained - * to not be set to null. - * - * @return string DBMS specific SQL code portion that should be used to - * declare the specified field. - */ - public function getNativeDeclaration(array $field) - { - switch ($field['type']) { - case 'char': - case 'string': - case 'array': - case 'object': - case 'varchar': - $length = (isset($field['length']) && $field['length']) ? $field['length'] : null; - // TODO: $db->options['default_text_field_length']; - - $fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false; - - return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')') - : ($length ? 'VARCHAR('.$length.')' : 'TEXT'); - - case 'clob': - return 'TEXT'; - case 'blob': - return 'BYTEA'; - case 'enum': - case 'integer': - if (!empty($field['autoincrement'])) { - if (!empty($field['length'])) { - $length = $field['length']; - if ($length > 4) { - return 'BIGSERIAL PRIMARY KEY'; - } - } - return 'SERIAL PRIMARY KEY'; - } - if (!empty($field['length'])) { - $length = $field['length']; - if ($length <= 2) { - return 'SMALLINT'; - } elseif ($length == 3 || $length == 4) { - return 'INT'; - } elseif ($length > 4) { - return 'BIGINT'; - } - } - return 'INT'; - case 'boolean': - return 'BOOLEAN'; - case 'date': - return 'DATE'; - case 'time': - return 'TIME without time zone'; - case 'timestamp': - return 'TIMESTAMP without time zone'; - case 'float': - return 'FLOAT8'; - case 'decimal': - $length = !empty($field['length']) ? $field['length'] : 18; - return 'NUMERIC(' . $length . ',' . $this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES) . ')'; - default: - throw new Doctrine_DataDict_Pgsql_Exception('Unknown field type '. $field['type']); - } - } - /** - * Maps a native array description of a field to a portable Doctrine datatype and length - * - * @param array $field native field description - * - * @return array containing the various possible types, length, sign, fixed - */ - public function getPortableDeclaration(array $field) - { - - $length = (isset($field['length'])) ? $field['length'] : null; - if ($length == '-1' && isset($field['atttypmod'])) { - $length = $field['atttypmod'] - 4; - } - if ((int)$length <= 0) { - $length = null; - } - $type = array(); - $unsigned = $fixed = null; - - if( ! isset($field['name'])) - $field['name'] = ''; - - $db_type = strtolower($field['type']); - - switch ($db_type) { - case 'smallint': - case 'int2': - $type[] = 'integer'; - $unsigned = false; - $length = 2; - if ($length == '2') { - $type[] = 'boolean'; - if (preg_match('/^(is|has)/', $field['name'])) { - $type = array_reverse($type); - } - } - break; - case 'int': - case 'int4': - case 'integer': - case 'serial': - case 'serial4': - $type[] = 'integer'; - $unsigned = false; - $length = 4; - break; - case 'bigint': - case 'int8': - case 'bigserial': - case 'serial8': - $type[] = 'integer'; - $unsigned = false; - $length = 8; - break; - case 'bool': - case 'boolean': - $type[] = 'boolean'; - $length = 1; - break; - case 'text': - case 'varchar': - $fixed = false; - case 'unknown': - case 'char': - case 'bpchar': - $type[] = 'string'; - if ($length == '1') { - $type[] = 'boolean'; - if (preg_match('/^(is|has)/', $field['name'])) { - $type = array_reverse($type); - } - } elseif (strstr($db_type, 'text')) { - $type[] = 'clob'; - } - if ($fixed !== false) { - $fixed = true; - } - break; - case 'date': - $type[] = 'date'; - $length = null; - break; - case 'datetime': - case 'timestamp': - $type[] = 'timestamp'; - $length = null; - break; - case 'time': - $type[] = 'time'; - $length = null; - break; - case 'float': - case 'double': - case 'real': - $type[] = 'float'; - break; - case 'decimal': - case 'money': - case 'numeric': - $type[] = 'decimal'; - break; - case 'tinyblob': - case 'mediumblob': - case 'longblob': - case 'blob': - case 'bytea': - $type[] = 'blob'; - $length = null; - break; - case 'oid': - $type[] = 'blob'; - $type[] = 'clob'; - $length = null; - break; - case 'year': - $type[] = 'integer'; - $type[] = 'date'; - $length = null; - break; - default: - throw new Doctrine_DataDict_Pgsql_Exception('unknown database attribute type: '.$db_type); - } - - return array($type, $length, $unsigned, $fixed); - } - /** - * Obtain DBMS specific SQL code portion needed to declare an integer type - * field to be used in statements like CREATE TABLE. - * - * @param string $name name the field to be declared. - * @param array $field associative array with the name of the properties - * of the field being declared as array indexes. Currently, the types - * of supported field properties are as follows: - * - * unsigned - * Boolean flag that indicates whether the field should be - * declared as unsigned integer if possible. - * - * default - * Integer value to be used as default for this field. - * - * notnull - * Boolean flag that indicates whether this field is constrained - * to not be set to null. - * @return string DBMS specific SQL code portion that should be used to - * declare the specified field. - */ - public function getIntegerDeclaration($name, $field) - { - /** - if (!empty($field['unsigned'])) { - $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer"; - } - */ - - if ( ! empty($field['autoincrement'])) { - $name = $this->conn->quoteIdentifier($name, true); - return $name.' '.$this->getNativeDeclaration($field); - } - - $default = ''; - if (array_key_exists('default', $field)) { - if ($field['default'] === '') { - $field['default'] = empty($field['notnull']) ? null : 0; - } - $default = ' DEFAULT '.$this->conn->quote($field['default'], $field['type']); - } - /** - TODO: is this needed ? - elseif (empty($field['notnull'])) { - $default = ' DEFAULT NULL'; - } - */ - - $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; - $name = $this->conn->quoteIdentifier($name, true); - return $name . ' ' . $this->getNativeDeclaration($field) . $default . $notnull; - } -} +. + */ +/** + * @package Doctrine + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @author Konsta Vesterinen + * @author Paul Cooper + * @author Lukas Smith (PEAR MDB2 library) + * @version $Revision$ + * @category Object Relational Mapping + * @link www.phpdoctrine.com + * @since 1.0 + */ +class Doctrine_DataDict_Pgsql extends Doctrine_DataDict +{ + /** + * @param array $reservedKeyWords an array of reserved keywords by pgsql + */ + protected static $reservedKeyWords = array( + 'abort', + 'absolute', + 'access', + 'action', + 'add', + 'after', + 'aggregate', + 'all', + 'alter', + 'analyse', + 'analyze', + 'and', + 'any', + 'as', + 'asc', + 'assertion', + 'assignment', + 'at', + 'authorization', + 'backward', + 'before', + 'begin', + 'between', + 'bigint', + 'binary', + 'bit', + 'boolean', + 'both', + 'by', + 'cache', + 'called', + 'cascade', + 'case', + 'cast', + 'chain', + 'char', + 'character', + 'characteristics', + 'check', + 'checkpoint', + 'class', + 'close', + 'cluster', + 'coalesce', + 'collate', + 'column', + 'comment', + 'commit', + 'committed', + 'constraint', + 'constraints', + 'conversion', + 'convert', + 'copy', + 'create', + 'createdb', + 'createuser', + 'cross', + 'current_date', + 'current_time', + 'current_timestamp', + 'current_user', + 'cursor', + 'cycle', + 'database', + 'day', + 'deallocate', + 'dec', + 'decimal', + 'declare', + 'default', + 'deferrable', + 'deferred', + 'definer', + 'delete', + 'delimiter', + 'delimiters', + 'desc', + 'distinct', + 'do', + 'domain', + 'double', + 'drop', + 'each', + 'else', + 'encoding', + 'encrypted', + 'end', + 'escape', + 'except', + 'exclusive', + 'execute', + 'exists', + 'explain', + 'external', + 'extract', + 'false', + 'fetch', + 'float', + 'for', + 'force', + 'foreign', + 'forward', + 'freeze', + 'from', + 'full', + 'function', + 'get', + 'global', + 'grant', + 'group', + 'handler', + 'having', + 'hour', + 'ilike', + 'immediate', + 'immutable', + 'implicit', + 'in', + 'increment', + 'index', + 'inherits', + 'initially', + 'inner', + 'inout', + 'input', + 'insensitive', + 'insert', + 'instead', + 'int', + 'integer', + 'intersect', + 'interval', + 'into', + 'invoker', + 'is', + 'isnull', + 'isolation', + 'join', + 'key', + 'lancompiler', + 'language', + 'leading', + 'left', + 'level', + 'like', + 'limit', + 'listen', + 'load', + 'local', + 'localtime', + 'localtimestamp', + 'location', + 'lock', + 'match', + 'maxvalue', + 'minute', + 'minvalue', + 'mode', + 'month', + 'move', + 'names', + 'national', + 'natural', + 'nchar', + 'new', + 'next', + 'no', + 'nocreatedb', + 'nocreateuser', + 'none', + 'not', + 'nothing', + 'notify', + 'notnull', + 'null', + 'nullif', + 'numeric', + 'of', + 'off', + 'offset', + 'oids', + 'old', + 'on', + 'only', + 'operator', + 'option', + 'or', + 'order', + 'out', + 'outer', + 'overlaps', + 'overlay', + 'owner', + 'partial', + 'password', + 'path', + 'pendant', + 'placing', + 'position', + 'precision', + 'prepare', + 'primary', + 'prior', + 'privileges', + 'procedural', + 'procedure', + 'read', + 'real', + 'recheck', + 'references', + 'reindex', + 'relative', + 'rename', + 'replace', + 'reset', + 'restrict', + 'returns', + 'revoke', + 'right', + 'rollback', + 'row', + 'rule', + 'schema', + 'scroll', + 'second', + 'security', + 'select', + 'sequence', + 'serializable', + 'session', + 'session_user', + 'set', + 'setof', + 'share', + 'show', + 'similar', + 'simple', + 'smallint', + 'some', + 'stable', + 'start', + 'statement', + 'statistics', + 'stdin', + 'stdout', + 'storage', + 'strict', + 'substring', + 'sysid', + 'table', + 'temp', + 'template', + 'temporary', + 'then', + 'time', + 'timestamp', + 'to', + 'toast', + 'trailing', + 'transaction', + 'treat', + 'trigger', + 'trim', + 'true', + 'truncate', + 'trusted', + 'type', + 'unencrypted', + 'union', + 'unique', + 'unknown', + 'unlisten', + 'until', + 'update', + 'usage', + 'user', + 'using', + 'vacuum', + 'valid', + 'validator', + 'values', + 'varchar', + 'varying', + 'verbose', + 'version', + 'view', + 'volatile', + 'when', + 'where', + 'with', + 'without', + 'work', + 'write', + 'year', + 'zone' + ); + + /** + * Obtain DBMS specific SQL code portion needed to declare an text type + * field to be used in statements like CREATE TABLE. + * + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + */ + public function getNativeDeclaration(array $field) + { + switch ($field['type']) { + case 'char': + case 'string': + case 'array': + case 'object': + case 'varchar': + $length = (isset($field['length']) && $field['length']) ? $field['length'] : null; + // TODO: $db->options['default_text_field_length']; + + $fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false; + + return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$db->options['default_text_field_length'].')') + : ($length ? 'VARCHAR('.$length.')' : 'TEXT'); + + case 'clob': + return 'TEXT'; + case 'blob': + return 'BYTEA'; + case 'enum': + case 'integer': + if (!empty($field['autoincrement'])) { + if (!empty($field['length'])) { + $length = $field['length']; + if ($length > 4) { + return 'BIGSERIAL PRIMARY KEY'; + } + } + return 'SERIAL PRIMARY KEY'; + } + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 2) { + return 'SMALLINT'; + } elseif ($length == 3 || $length == 4) { + return 'INT'; + } elseif ($length > 4) { + return 'BIGINT'; + } + } + return 'INT'; + case 'boolean': + return 'BOOLEAN'; + case 'date': + return 'DATE'; + case 'time': + return 'TIME without time zone'; + case 'timestamp': + return 'TIMESTAMP without time zone'; + case 'float': + return 'FLOAT8'; + case 'decimal': + $length = !empty($field['length']) ? $field['length'] : 18; + return 'NUMERIC(' . $length . ',' . $this->conn->getAttribute(Doctrine::ATTR_DECIMAL_PLACES) . ')'; + default: + throw new Doctrine_DataDict_Pgsql_Exception('Unknown field type '. $field['type']); + } + } + /** + * Maps a native array description of a field to a portable Doctrine datatype and length + * + * @param array $field native field description + * + * @return array containing the various possible types, length, sign, fixed + */ + public function getPortableDeclaration(array $field) + { + + $length = (isset($field['length'])) ? $field['length'] : null; + if ($length == '-1' && isset($field['atttypmod'])) { + $length = $field['atttypmod'] - 4; + } + if ((int)$length <= 0) { + $length = null; + } + $type = array(); + $unsigned = $fixed = null; + + if ( ! isset($field['name'])) { + $field['name'] = ''; + } + + $db_type = strtolower($field['type']); + + switch ($db_type) { + case 'smallint': + case 'int2': + $type[] = 'integer'; + $unsigned = false; + $length = 2; + if ($length == '2') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } + break; + case 'int': + case 'int4': + case 'integer': + case 'serial': + case 'serial4': + $type[] = 'integer'; + $unsigned = false; + $length = 4; + break; + case 'bigint': + case 'int8': + case 'bigserial': + case 'serial8': + $type[] = 'integer'; + $unsigned = false; + $length = 8; + break; + case 'bool': + case 'boolean': + $type[] = 'boolean'; + $length = 1; + break; + case 'text': + case 'varchar': + $fixed = false; + case 'unknown': + case 'char': + case 'bpchar': + $type[] = 'string'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } elseif (strstr($db_type, 'text')) { + $type[] = 'clob'; + } + if ($fixed !== false) { + $fixed = true; + } + break; + case 'date': + $type[] = 'date'; + $length = null; + break; + case 'datetime': + case 'timestamp': + $type[] = 'timestamp'; + $length = null; + break; + case 'time': + $type[] = 'time'; + $length = null; + break; + case 'float': + case 'double': + case 'real': + $type[] = 'float'; + break; + case 'decimal': + case 'money': + case 'numeric': + $type[] = 'decimal'; + break; + case 'tinyblob': + case 'mediumblob': + case 'longblob': + case 'blob': + case 'bytea': + $type[] = 'blob'; + $length = null; + break; + case 'oid': + $type[] = 'blob'; + $type[] = 'clob'; + $length = null; + break; + case 'year': + $type[] = 'integer'; + $type[] = 'date'; + $length = null; + break; + default: + throw new Doctrine_DataDict_Pgsql_Exception('unknown database attribute type: '.$db_type); + } + + return array($type, $length, $unsigned, $fixed); + } + /** + * Obtain DBMS specific SQL code portion needed to declare an integer type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * unsigned + * Boolean flag that indicates whether the field should be + * declared as unsigned integer if possible. + * + * default + * Integer value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + */ + public function getIntegerDeclaration($name, $field) + { + /** + if (!empty($field['unsigned'])) { + $db->warnings[] = "unsigned integer field \"$name\" is being declared as signed integer"; + } + */ + + if ( ! empty($field['autoincrement'])) { + $name = $this->conn->quoteIdentifier($name, true); + return $name.' '.$this->getNativeDeclaration($field); + } + + $default = ''; + if (array_key_exists('default', $field)) { + if ($field['default'] === '') { + $field['default'] = empty($field['notnull']) ? null : 0; + } + $default = ' DEFAULT '.$this->conn->quote($field['default'], $field['type']); + } + /** + TODO: is this needed ? + elseif (empty($field['notnull'])) { + $default = ' DEFAULT NULL'; + } + */ + + $notnull = empty($field['notnull']) ? '' : ' NOT NULL'; + $name = $this->conn->quoteIdentifier($name, true); + return $name . ' ' . $this->getNativeDeclaration($field) . $default . $notnull; + } +} diff --git a/lib/Doctrine/DataDict/Sqlite.php b/lib/Doctrine/DataDict/Sqlite.php index d58898a44..bab15c097 100644 --- a/lib/Doctrine/DataDict/Sqlite.php +++ b/lib/Doctrine/DataDict/Sqlite.php @@ -1,285 +1,286 @@ -. - */ -Doctrine::autoload('Doctrine_DataDict'); -/** - * @package Doctrine - * @license http://www.opensource.org/licenses/lgpl-license.php LGPL - * @author Konsta Vesterinen - * @author Lukas Smith (PEAR MDB2 library) - * @version $Revision$ - * @category Object Relational Mapping - * @link www.phpdoctrine.com - * @since 1.0 - */ -class Doctrine_DataDict_Sqlite extends Doctrine_DataDict -{ - /** - * Obtain DBMS specific SQL code portion needed to declare an text type - * field to be used in statements like CREATE TABLE. - * - * @param array $field associative array with the name of the properties - * of the field being declared as array indexes. Currently, the types - * of supported field properties are as follows: - * - * length - * Integer value that determines the maximum length of the text - * field. If this argument is missing the field should be - * declared to have the longest length allowed by the DBMS. - * - * default - * Text value to be used as default for this field. - * - * notnull - * Boolean flag that indicates whether this field is constrained - * to not be set to null. - * @author Lukas Smith (PEAR MDB2 library) - * @return string DBMS specific SQL code portion that should be used to - * declare the specified field. - */ - public function getNativeDeclaration(array $field) - { - switch ($field['type']) { - case 'text': - case 'object': - case 'array': - case 'string': - case 'char': - case 'gzip': - case 'varchar': - $length = (isset($field['length']) && $field['length']) ? $field['length'] : null; - - $fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false; - - return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$this->conn->getAttribute(Doctrine::ATTR_DEFAULT_TEXTFLD_LENGTH).')') - : ($length ? 'VARCHAR('.$length.')' : 'TEXT'); - case 'clob': - if (!empty($field['length'])) { - $length = $field['length']; - if ($length <= 255) { - return 'TINYTEXT'; - } elseif ($length <= 65535) { - return 'TEXT'; - } elseif ($length <= 16777215) { - return 'MEDIUMTEXT'; - } - } - return 'LONGTEXT'; - case 'blob': - if (!empty($field['length'])) { - $length = $field['length']; - if ($length <= 255) { - return 'TINYBLOB'; - } elseif ($length <= 65535) { - return 'BLOB'; - } elseif ($length <= 16777215) { - return 'MEDIUMBLOB'; - } - } - return 'LONGBLOB'; - case 'enum': - case 'integer': - case 'boolean': - return 'INTEGER'; - case 'date': - return 'DATE'; - case 'time': - return 'TIME'; - case 'timestamp': - return 'DATETIME'; - case 'float': - case 'double': - return 'DOUBLE';//($db->options['fixed_float'] ? '('. - //($db->options['fixed_float']+2).','.$db->options['fixed_float'].')' : ''); - case 'decimal': - $length = !empty($field['length']) ? $field['length'] : 18; - return 'DECIMAL('.$length.','.$db->options['decimal_places'].')'; - } - throw new Doctrine_DataDict_Sqlite_Exception('Unknown datatype ' . $field['type']); - } - /** - * Maps a native array description of a field to Doctrine datatype and length - * - * @param array $field native field description - * @return array containing the various possible types, length, sign, fixed - */ - public function getPortableDeclaration(array $field) - { - $dbType = strtolower($field['type']); - $length = (isset($field['length'])) ? $field['length'] : null; - $unsigned = (isset($field['unsigned'])) ? $field['unsigned'] : null; - $fixed = null; - $type = array(); - - if( ! isset($field['name'])) - $field['name'] = ''; - - switch ($dbType) { - case 'boolean': - $type[] = 'boolean'; - break; - case 'tinyint': - $type[] = 'integer'; - $type[] = 'boolean'; - if (preg_match('/^(is|has)/', $field['name'])) { - $type = array_reverse($type); - } - $unsigned = preg_match('/ unsigned/i', $field['type']); - $length = 1; - break; - case 'smallint': - $type[] = 'integer'; - $unsigned = preg_match('/ unsigned/i', $field['type']); - $length = 2; - break; - case 'mediumint': - $type[] = 'integer'; - $unsigned = preg_match('/ unsigned/i', $field['type']); - $length = 3; - break; - case 'int': - case 'integer': - case 'serial': - $type[] = 'integer'; - $unsigned = preg_match('/ unsigned/i', $field['type']); - $length = 4; - break; - case 'bigint': - case 'bigserial': - $type[] = 'integer'; - $unsigned = preg_match('/ unsigned/i', $field['type']); - $length = 8; - break; - case 'clob': - case 'tinytext': - case 'mediumtext': - case 'longtext': - case 'text': - case 'varchar': - case 'varchar2': - $fixed = false; - case 'char': - $type[] = 'text'; - if ($length == '1') { - $type[] = 'boolean'; - if (preg_match('/^(is|has)/', $field['name'])) { - $type = array_reverse($type); - } - } elseif (strstr($dbType, 'text')) { - $type[] = 'clob'; - } - if ($fixed !== false) { - $fixed = true; - } - break; - case 'date': - $type[] = 'date'; - $length = null; - break; - case 'datetime': - case 'timestamp': - $type[] = 'timestamp'; - $length = null; - break; - case 'time': - $type[] = 'time'; - $length = null; - break; - case 'float': - case 'double': - case 'real': - $type[] = 'float'; - $length = null; - break; - case 'decimal': - case 'numeric': - $type[] = 'decimal'; - $length = null; - break; - case 'tinyblob': - case 'mediumblob': - case 'longblob': - case 'blob': - $type[] = 'blob'; - $length = null; - break; - case 'year': - $type[] = 'integer'; - $type[] = 'date'; - $length = null; - break; - default: - throw new Doctrine_DataDict_Sqlite_Exception('unknown database attribute type: '.$dbType); - } - - return array($type, $length, $unsigned, $fixed); - } - /** - * Obtain DBMS specific SQL code portion needed to declare an integer type - * field to be used in statements like CREATE TABLE. - * - * @param string $name name the field to be declared. - * @param array $field associative array with the name of the properties - * of the field being declared as array indexes. - * Currently, the types of supported field - * properties are as follows: - * - * unsigned - * Boolean flag that indicates whether the field - * should be declared as unsigned integer if - * possible. - * - * default - * Integer value to be used as default for this - * field. - * - * notnull - * Boolean flag that indicates whether this field is - * constrained to not be set to null. - * @return string DBMS specific SQL code portion that should be used to - * declare the specified field. - * @access protected - */ - public function getIntegerDeclaration($name, array $field) - { - $default = $autoinc = ''; - $type = $this->getNativeDeclaration($field); - - if (isset($field['autoincrement']) && $field['autoincrement']) { - $autoinc = ' PRIMARY KEY AUTOINCREMENT'; - $type = 'INTEGER'; - } elseif (array_key_exists('default', $field)) { - if ($field['default'] === '') { - $field['default'] = empty($field['notnull']) ? null : 0; - } - $default = ' DEFAULT ' . $this->conn->quote($field['default'], $field['type']); - }/** - elseif (empty($field['notnull'])) { - $default = ' DEFAULT NULL'; - } - */ - - $notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : ''; - $unsigned = (isset($field['unsigned']) && $field['unsigned']) ? ' UNSIGNED' : ''; - - $name = $this->conn->quoteIdentifier($name, true); - return $name . ' ' . $type . $unsigned . $default . $notnull . $autoinc; - } -} +. + */ +Doctrine::autoload('Doctrine_DataDict'); +/** + * @package Doctrine + * @license http://www.opensource.org/licenses/lgpl-license.php LGPL + * @author Konsta Vesterinen + * @author Lukas Smith (PEAR MDB2 library) + * @version $Revision$ + * @category Object Relational Mapping + * @link www.phpdoctrine.com + * @since 1.0 + */ +class Doctrine_DataDict_Sqlite extends Doctrine_DataDict +{ + /** + * Obtain DBMS specific SQL code portion needed to declare an text type + * field to be used in statements like CREATE TABLE. + * + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. Currently, the types + * of supported field properties are as follows: + * + * length + * Integer value that determines the maximum length of the text + * field. If this argument is missing the field should be + * declared to have the longest length allowed by the DBMS. + * + * default + * Text value to be used as default for this field. + * + * notnull + * Boolean flag that indicates whether this field is constrained + * to not be set to null. + * @author Lukas Smith (PEAR MDB2 library) + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + */ + public function getNativeDeclaration(array $field) + { + switch ($field['type']) { + case 'text': + case 'object': + case 'array': + case 'string': + case 'char': + case 'gzip': + case 'varchar': + $length = (isset($field['length']) && $field['length']) ? $field['length'] : null; + + $fixed = ((isset($field['fixed']) && $field['fixed']) || $field['type'] == 'char') ? true : false; + + return $fixed ? ($length ? 'CHAR('.$length.')' : 'CHAR('.$this->conn->getAttribute(Doctrine::ATTR_DEFAULT_TEXTFLD_LENGTH).')') + : ($length ? 'VARCHAR('.$length.')' : 'TEXT'); + case 'clob': + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 255) { + return 'TINYTEXT'; + } elseif ($length <= 65535) { + return 'TEXT'; + } elseif ($length <= 16777215) { + return 'MEDIUMTEXT'; + } + } + return 'LONGTEXT'; + case 'blob': + if (!empty($field['length'])) { + $length = $field['length']; + if ($length <= 255) { + return 'TINYBLOB'; + } elseif ($length <= 65535) { + return 'BLOB'; + } elseif ($length <= 16777215) { + return 'MEDIUMBLOB'; + } + } + return 'LONGBLOB'; + case 'enum': + case 'integer': + case 'boolean': + return 'INTEGER'; + case 'date': + return 'DATE'; + case 'time': + return 'TIME'; + case 'timestamp': + return 'DATETIME'; + case 'float': + case 'double': + return 'DOUBLE';//($db->options['fixed_float'] ? '('. + //($db->options['fixed_float']+2).','.$db->options['fixed_float'].')' : ''); + case 'decimal': + $length = !empty($field['length']) ? $field['length'] : 18; + return 'DECIMAL('.$length.','.$db->options['decimal_places'].')'; + } + throw new Doctrine_DataDict_Sqlite_Exception('Unknown datatype ' . $field['type']); + } + /** + * Maps a native array description of a field to Doctrine datatype and length + * + * @param array $field native field description + * @return array containing the various possible types, length, sign, fixed + */ + public function getPortableDeclaration(array $field) + { + $dbType = strtolower($field['type']); + $length = (isset($field['length'])) ? $field['length'] : null; + $unsigned = (isset($field['unsigned'])) ? $field['unsigned'] : null; + $fixed = null; + $type = array(); + + if ( ! isset($field['name'])) { + $field['name'] = ''; + } + + switch ($dbType) { + case 'boolean': + $type[] = 'boolean'; + break; + case 'tinyint': + $type[] = 'integer'; + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 1; + break; + case 'smallint': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 2; + break; + case 'mediumint': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 3; + break; + case 'int': + case 'integer': + case 'serial': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 4; + break; + case 'bigint': + case 'bigserial': + $type[] = 'integer'; + $unsigned = preg_match('/ unsigned/i', $field['type']); + $length = 8; + break; + case 'clob': + case 'tinytext': + case 'mediumtext': + case 'longtext': + case 'text': + case 'varchar': + case 'varchar2': + $fixed = false; + case 'char': + $type[] = 'text'; + if ($length == '1') { + $type[] = 'boolean'; + if (preg_match('/^(is|has)/', $field['name'])) { + $type = array_reverse($type); + } + } elseif (strstr($dbType, 'text')) { + $type[] = 'clob'; + } + if ($fixed !== false) { + $fixed = true; + } + break; + case 'date': + $type[] = 'date'; + $length = null; + break; + case 'datetime': + case 'timestamp': + $type[] = 'timestamp'; + $length = null; + break; + case 'time': + $type[] = 'time'; + $length = null; + break; + case 'float': + case 'double': + case 'real': + $type[] = 'float'; + $length = null; + break; + case 'decimal': + case 'numeric': + $type[] = 'decimal'; + $length = null; + break; + case 'tinyblob': + case 'mediumblob': + case 'longblob': + case 'blob': + $type[] = 'blob'; + $length = null; + break; + case 'year': + $type[] = 'integer'; + $type[] = 'date'; + $length = null; + break; + default: + throw new Doctrine_DataDict_Sqlite_Exception('unknown database attribute type: '.$dbType); + } + + return array($type, $length, $unsigned, $fixed); + } + /** + * Obtain DBMS specific SQL code portion needed to declare an integer type + * field to be used in statements like CREATE TABLE. + * + * @param string $name name the field to be declared. + * @param array $field associative array with the name of the properties + * of the field being declared as array indexes. + * Currently, the types of supported field + * properties are as follows: + * + * unsigned + * Boolean flag that indicates whether the field + * should be declared as unsigned integer if + * possible. + * + * default + * Integer value to be used as default for this + * field. + * + * notnull + * Boolean flag that indicates whether this field is + * constrained to not be set to null. + * @return string DBMS specific SQL code portion that should be used to + * declare the specified field. + * @access protected + */ + public function getIntegerDeclaration($name, array $field) + { + $default = $autoinc = ''; + $type = $this->getNativeDeclaration($field); + + if (isset($field['autoincrement']) && $field['autoincrement']) { + $autoinc = ' PRIMARY KEY AUTOINCREMENT'; + $type = 'INTEGER'; + } elseif (array_key_exists('default', $field)) { + if ($field['default'] === '') { + $field['default'] = empty($field['notnull']) ? null : 0; + } + $default = ' DEFAULT ' . $this->conn->quote($field['default'], $field['type']); + }/** + elseif (empty($field['notnull'])) { + $default = ' DEFAULT NULL'; + } + */ + + $notnull = (isset($field['notnull']) && $field['notnull']) ? ' NOT NULL' : ''; + $unsigned = (isset($field['unsigned']) && $field['unsigned']) ? ' UNSIGNED' : ''; + + $name = $this->conn->quoteIdentifier($name, true); + return $name . ' ' . $type . $unsigned . $default . $notnull . $autoinc; + } +} diff --git a/lib/Doctrine/Validator.php b/lib/Doctrine/Validator.php index 208db0367..20005a937 100644 --- a/lib/Doctrine/Validator.php +++ b/lib/Doctrine/Validator.php @@ -182,10 +182,9 @@ class Doctrine_Validator */ private function validateLength($column, $key, $value) { - if($column[0] == "timestamp") { + if ($column[0] == "timestamp") { return true; - } - else if ($column[0] == "array" || $column[0] == "object") { + } else if ($column[0] == "array" || $column[0] == "object") { $length = strlen(serialize($value)); } else { $length = strlen($value);