From 5bb449386450b5dee389dd2c338361ddbbe5eeb7 Mon Sep 17 00:00:00 2001 From: zYne Date: Thu, 8 Nov 2007 23:03:28 +0000 Subject: [PATCH] Drafting the initial CTI support, only works for simple inserts now --- lib/Doctrine/Connection/UnitOfWork.php | 118 +++++++++++++++++-------- lib/Doctrine/Export.php | 14 ++- lib/Doctrine/Table.php | 87 ++++++++++++++++-- 3 files changed, 173 insertions(+), 46 deletions(-) diff --git a/lib/Doctrine/Connection/UnitOfWork.php b/lib/Doctrine/Connection/UnitOfWork.php index db20cf27f..15e3925dd 100644 --- a/lib/Doctrine/Connection/UnitOfWork.php +++ b/lib/Doctrine/Connection/UnitOfWork.php @@ -586,53 +586,99 @@ class Doctrine_Connection_UnitOfWork extends Doctrine_Connection_Module $record->preInsert($event); - $record->getTable()->getRecordListener()->preInsert($event); + $table = $record->getTable(); + + $table->getRecordListener()->preInsert($event); if ( ! $event->skipOperation) { - $array = $record->getPrepared(); - - if (empty($array)) { - return false; - } - $table = $record->getTable(); - $keys = (array) $table->getIdentifier(); - - $seq = $record->getTable()->sequenceName; - - if ( ! empty($seq)) { - $id = $this->conn->sequence->nextId($seq); - $name = $record->getTable()->getIdentifier(); - $array[$name] = $id; - - $record->assignIdentifier($id); - } - - $this->conn->insert($table->getTableName(), $array); - - if (empty($seq) && count($keys) == 1 && $keys[0] == $table->getIdentifier() && - $table->getIdentifierType() != Doctrine::IDENTIFIER_NATURAL) { - - if (strtolower($this->conn->getName()) == 'pgsql') { - $seq = $table->getTableName() . '_' . $keys[0]; + if (count($table->getOption('joinedParents')) > 0) { + $dataSet = array(); + + $component = $table->getComponentName(); + + $array = $record->getPrepared(); + + foreach ($table->getColumns() as $column => $definition) { + if (isset($definition['primary']) && $definition['primary']) { + continue; + } + + if (isset($definition['owner'])) { + $dataSet[$definition['owner']][$column] = $array[$column]; + } else { + $dataSet[$component][$column] = $array[$column]; + } } - - $id = $this->conn->sequence->lastInsertId($seq); - - if ( ! $id) { - throw new Doctrine_Connection_Exception("Couldn't get last insert identifier."); + + $classes = $table->getOption('joinedParents'); + $classes[] = $component; + + foreach ($classes as $k => $parent) { + if ($k === 0) { + $rootRecord = new $parent(); + + $rootRecord->merge($dataSet[$parent]); + + $this->processSingleInsert($rootRecord); + } else { + foreach ((array) $rootRecord->identifier() as $id => $value) { + $dataSet[$parent][$id] = $value; + } + + $this->conn->insert($this->conn->getTable($parent)->getTableName(), $dataSet[$parent]); + } } - - $record->assignIdentifier($id); } else { - $record->assignIdentifier(true); + $this->processSingleInsert($record); } } - $record->getTable()->addRecord($record); - $record->getTable()->getRecordListener()->postInsert($event); + $table->addRecord($record); + + $table->getRecordListener()->postInsert($event); $record->postInsert($event); return true; } + public function processSingleInsert(Doctrine_Record $record) + { + $array = $record->getPrepared(); + + if (empty($array)) { + return false; + } + $table = $record->getTable(); + $keys = (array) $table->getIdentifier(); + + $seq = $record->getTable()->sequenceName; + + if ( ! empty($seq)) { + $id = $this->conn->sequence->nextId($seq); + $name = $record->getTable()->getIdentifier(); + $array[$name] = $id; + + $record->assignIdentifier($id); + } + + $this->conn->insert($table->getTableName(), $array); + + if (empty($seq) && count($keys) == 1 && $keys[0] == $table->getIdentifier() && + $table->getIdentifierType() != Doctrine::IDENTIFIER_NATURAL) { + + if (strtolower($this->conn->getName()) == 'pgsql') { + $seq = $table->getTableName() . '_' . $keys[0]; + } + + $id = $this->conn->sequence->lastInsertId($seq); + + if ( ! $id) { + throw new Doctrine_Connection_Exception("Couldn't get last insert identifier."); + } + + $record->assignIdentifier($id); + } else { + $record->assignIdentifier(true); + } + } } diff --git a/lib/Doctrine/Export.php b/lib/Doctrine/Export.php index 58c4de189..3a3734225 100644 --- a/lib/Doctrine/Export.php +++ b/lib/Doctrine/Export.php @@ -1131,7 +1131,17 @@ class Doctrine_Export extends Doctrine_Connection_Module foreach ($models as $name) { $record = new $name(); $table = $record->getTable(); - + + $parents = $table->getOption('joinedParents'); + + foreach ($parents as $parent) { + $data = $table->getConnection()->getTable($parent)->getExportableFormat(); + + $query = $this->conn->export->createTableSql($data['tableName'], $data['columns'], $data['options']); + + $sql = array_merge($sql, (array) $query); + } + $data = $table->getExportableFormat(); $query = $this->conn->export->createTableSql($data['tableName'], $data['columns'], $data['options']); @@ -1242,4 +1252,4 @@ class Doctrine_Export extends Doctrine_Connection_Module } } } -} \ No newline at end of file +} diff --git a/lib/Doctrine/Table.php b/lib/Doctrine/Table.php index b78476510..eb7c215be 100644 --- a/lib/Doctrine/Table.php +++ b/lib/Doctrine/Table.php @@ -35,7 +35,7 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable { /** - * @var array $data temporary data which is then loaded into Doctrine_Record::$data + * @var array $data temporary data which is then loaded into Doctrine_Record::$_data */ protected $_data = array(); @@ -257,6 +257,48 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable } else { $class = new ReflectionClass($class); } + + + $this->_options['joinedParents'] = array(); + + foreach (array_reverse($this->_options['parents']) as $parent) { + if ($parent === $class->getName()) { + continue; + } + + $table = $this->_conn->getTable($parent); + + $found = false; + $columns = $table->getColumns(); + + foreach ($columns as $column => $definition) { + if ( ! isset($definition['primary'])) { + if (isset($this->_columns[$column])) { + $found = true; + break; + } else { + if ( ! isset($columns[$column]['owner'])) { + $columns[$column]['owner'] = $table->getComponentName(); + } + + $this->_options['joinedParents'][] = $columns[$column]['owner']; + } + } else { + unset($columns[$column]); + } + } + + if ($found) { + continue; + } + + $this->_columns = array_merge($columns, $this->_columns); + + break; + } + + $this->_options['joinedParents'] = array_values(array_unique($this->_options['joinedParents'])); + $this->_options['declaringClass'] = $class; // set the table definition for the given tree implementation @@ -276,13 +318,38 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable { switch (count($this->_identifier)) { case 0: - $this->_columns = array_merge(array('id' => - array('type' => 'integer', - 'length' => 20, - 'autoincrement' => true, - 'primary' => true)), $this->_columns); - $this->_identifier = 'id'; - $this->_identifierType = Doctrine::IDENTIFIER_AUTOINC; + if ( ! empty($this->_options['joinedParents'])) { + $root = current($this->_options['joinedParents']); + + $table = $this->_conn->getTable($root); + + $this->_identifier = $table->getIdentifier(); + + $this->_identifierType = ($table->getIdentifierType() !== Doctrine::IDENTIFIER_AUTOINC) + ? $table->getIdentifierType() : Doctrine::IDENTIFIER_NATURAL; + + // add all inherited primary keys + foreach ((array) $this->_identifier as $id) { + $definition = $table->getDefinitionOf($id); + + // inherited primary keys shouldn't contain autoinc + // and sequence definitions + unset($definition['autoincrement']); + unset($definition['sequence']); + + // add the inherited primary key column + $this->_columns = array_merge(array($id => $definition), $this->_columns); + } + + } else { + $this->_columns = array_merge(array('id' => + array('type' => 'integer', + 'length' => 20, + 'autoincrement' => true, + 'primary' => true)), $this->_columns); + $this->_identifier = 'id'; + $this->_identifierType = Doctrine::IDENTIFIER_AUTOINC; + } $this->columnCount++; break; case 1: @@ -390,6 +457,10 @@ class Doctrine_Table extends Doctrine_Configurable implements Countable foreach ($this->getColumns() as $name => $column) { $definition = $column; + if (isset($column['owner'])) { + continue; + } + switch ($definition['type']) { case 'enum': if (isset($definition['default'])) {