protected function createTaggingTable() { $table = $this->getTable(); $database = $table->getDatabase(); $pks = $this->getTable()->getPrimaryKey(); if (count($pks) > 1) { throw new EngineException('The Taggable behavior does not support tables with composite primary keys'); } $taggingTableName = $this->getTaggingTableName(); if ($database->hasTable($taggingTableName)) { $this->taggingTable = $database->getTable($taggingTableName); } else { $this->taggingTable = $database->addTable(array('name' => $taggingTableName, 'phpName' => $this->replaceTokens($this->getParameter('tagging_table_phpname')), 'package' => $table->getPackage(), 'schema' => $table->getSchema(), 'namespace' => '\\' . $table->getNamespace())); // every behavior adding a table should re-execute database behaviors // see bug 2188 http://www.propelorm.org/changeset/2188 foreach ($database->getBehaviors() as $behavior) { $behavior->modifyDatabase(); } } if ($this->taggingTable->hasColumn('tag_id')) { $tagFkColumn = $this->taggingTable->getColumn('tag_id'); } else { $tagFkColumn = $this->taggingTable->addColumn(array('name' => 'tag_id', 'type' => PropelTypes::INTEGER, 'primaryKey' => 'true')); } if ($this->taggingTable->hasColumn($table->getName() . '_id')) { $objFkColumn = $this->taggingTable->getColumn($table->getName() . '_id'); } else { $objFkColumn = $this->taggingTable->addColumn(array('name' => $table->getName() . '_id', 'type' => PropelTypes::INTEGER, 'primaryKey' => 'true')); } $this->taggingTable->setIsCrossRef(true); $fkTag = new ForeignKey(); $fkTag->setForeignTableCommonName($this->tagTable->getCommonName()); $fkTag->setForeignSchemaName($this->tagTable->getSchema()); $fkTag->setOnDelete(ForeignKey::CASCADE); $fkTag->setOnUpdate(ForeignKey::CASCADE); $tagColumn = $this->tagTable->getColumn('id'); $fkTag->addReference($tagFkColumn->getName(), $tagColumn->getName()); $this->taggingTable->addForeignKey($fkTag); $fkObj = new ForeignKey(); $fkObj->setForeignTableCommonName($this->getTable()->getCommonName()); $fkObj->setForeignSchemaName($this->getTable()->getSchema()); $fkObj->setOnDelete(ForeignKey::CASCADE); $fkObj->setOnUpdate(ForeignKey::CASCADE); foreach ($pks as $column) { $fkObj->addReference($objFkColumn->getName(), $column->getName()); } $this->taggingTable->addForeignKey($fkObj); }
/** * Creates a column definition as required by the DBAL from an ORM field mapping definition. * * @param ClassMetadata $class The class that owns the field mapping. * @param array $mapping The field mapping. * @param Table $table * @return array The portable column definition as required by the DBAL. */ private function _gatherColumn($class, array $mapping, $table) { $columnName = $this->quoteStrategy->getColumnName($mapping['fieldName'], $class, $this->platform); $columnType = $mapping['type']; $options = array(); $options['length'] = isset($mapping['length']) ? $mapping['length'] : null; $options['notnull'] = isset($mapping['nullable']) ? !$mapping['nullable'] : true; if ($class->isInheritanceTypeSingleTable() && count($class->parentClasses) > 0) { $options['notnull'] = false; } $options['platformOptions'] = array(); $options['platformOptions']['version'] = $class->isVersioned && $class->versionField == $mapping['fieldName'] ? true : false; if (strtolower($columnType) == 'string' && $options['length'] === null) { $options['length'] = 255; } if (isset($mapping['precision'])) { $options['precision'] = $mapping['precision']; } if (isset($mapping['scale'])) { $options['scale'] = $mapping['scale']; } if (isset($mapping['default'])) { $options['default'] = $mapping['default']; } if (isset($mapping['columnDefinition'])) { $options['columnDefinition'] = $mapping['columnDefinition']; } if (isset($mapping['options'])) { $knownOptions = array('comment', 'unsigned', 'fixed', 'default'); foreach ($knownOptions as $knownOption) { if (isset($mapping['options'][$knownOption])) { $options[$knownOption] = $mapping['options'][$knownOption]; unset($mapping['options'][$knownOption]); } } $options['customSchemaOptions'] = $mapping['options']; } if ($class->isIdGeneratorIdentity() && $class->getIdentifierFieldNames() == array($mapping['fieldName'])) { $options['autoincrement'] = true; } if ($class->isInheritanceTypeJoined() && $class->name != $class->rootEntityName) { $options['autoincrement'] = false; } if ($table->hasColumn($columnName)) { // required in some inheritance scenarios $table->changeColumn($columnName, $options); } else { $table->addColumn($columnName, $columnType, $options); } $isUnique = isset($mapping['unique']) ? $mapping['unique'] : false; if ($isUnique) { $table->addUniqueIndex(array($columnName)); } }
/** * Returns the difference between the tables $table1 and $table2. * * If there are no differences this method returns the boolean false. * * @param Table $table1 * @param Table $table2 * * @return bool|TableDiff */ public function diffTable(Table $table1, Table $table2) { $changes = 0; $tableDifferences = new TableDiff($table1->getName()); $table1Columns = $table1->getColumns(); $table2Columns = $table2->getColumns(); /* See if all the fields in table 1 exist in table 2 */ foreach ($table2Columns as $columnName => $column) { if (!$table1->hasColumn($columnName)) { $tableDifferences->addedColumns[$columnName] = $column; $changes++; } } /* See if there are any removed fields in table 2 */ foreach ($table1Columns as $columnName => $column) { if (!$table2->hasColumn($columnName)) { $tableDifferences->removedColumns[$columnName] = $column; $changes++; } } foreach ($table1Columns as $columnName => $column) { if ($table2->hasColumn($columnName)) { $changedProperties = $this->diffColumn($column, $table2->getColumn($columnName)); if (count($changedProperties)) { $columnDiff = new ColumnDiff($column->getName(), $table2->getColumn($columnName), $changedProperties); $tableDifferences->changedColumns[$column->getName()] = $columnDiff; $changes++; } } } $this->detectColumnRenamings($tableDifferences); $table1Indexes = $table1->getIndexes(); $table2Indexes = $table2->getIndexes(); foreach ($table2Indexes as $index2Name => $index2Definition) { foreach ($table1Indexes as $index1Name => $index1Definition) { if ($this->diffIndex($index1Definition, $index2Definition) === false) { unset($table1Indexes[$index1Name]); unset($table2Indexes[$index2Name]); } else { if ($index1Name == $index2Name) { $tableDifferences->changedIndexes[$index2Name] = $table2Indexes[$index2Name]; unset($table1Indexes[$index1Name]); unset($table2Indexes[$index2Name]); $changes++; } } } } foreach ($table1Indexes as $index1Name => $index1Definition) { $tableDifferences->removedIndexes[$index1Name] = $index1Definition; $changes++; } foreach ($table2Indexes as $index2Name => $index2Definition) { $tableDifferences->addedIndexes[$index2Name] = $index2Definition; $changes++; } $fromFkeys = $table1->getForeignKeys(); $toFkeys = $table2->getForeignKeys(); foreach ($fromFkeys as $key1 => $constraint1) { foreach ($toFkeys as $key2 => $constraint2) { if ($this->diffForeignKey($constraint1, $constraint2) === false) { unset($fromFkeys[$key1]); unset($toFkeys[$key2]); } else { if (strtolower($constraint1->getName()) == strtolower($constraint2->getName())) { $tableDifferences->changedForeignKeys[] = $constraint2; $changes++; unset($fromFkeys[$key1]); unset($toFkeys[$key2]); } } } } foreach ($fromFkeys as $key1 => $constraint1) { $tableDifferences->removedForeignKeys[] = $constraint1; $changes++; } foreach ($toFkeys as $key2 => $constraint2) { $tableDifferences->addedForeignKeys[] = $constraint2; $changes++; } return $changes ? $tableDifferences : false; }
/** * Adds Indexes to the specified table. * * @param Table $table The Table model class to add columns to. */ protected function addIndexes(Table $table) { $stmt = $this->dbh->query("SELECT COLUMN_NAME, INDEX_NAME FROM USER_IND_COLUMNS WHERE TABLE_NAME = '" . $table->getName() . "' ORDER BY COLUMN_NAME"); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); $indices = array(); foreach ($rows as $row) { $indices[$row['INDEX_NAME']][] = $row['COLUMN_NAME']; } foreach ($indices as $indexName => $columnNames) { $index = new Index($indexName); foreach ($columnNames as $columnName) { // Oracle deals with complex indices using an internal reference, so... // let's ignore this kind of index if ($table->hasColumn($columnName)) { $index->addColumn($table->getColumn($columnName)); } } // since some of the columns are pruned above, we must only add an index if it has columns if ($index->hasColumns()) { $table->addIndex($index); } } }
/** * Creates a column definition as required by the DBAL from an ORM field mapping definition. * * @param ClassMetadata $class The class that owns the field mapping. * @param array $mapping The field mapping. * @param Table $table * @return array The portable column definition as required by the DBAL. */ private function _gatherColumn($class, array $mapping, $table) { $columnName = $class->getQuotedColumnName($mapping['fieldName'], $this->_platform); $columnType = $mapping['type']; $options = array(); $options['length'] = isset($mapping['length']) ? $mapping['length'] : null; $options['notnull'] = isset($mapping['nullable']) ? !$mapping['nullable'] : true; $options['platformOptions'] = array(); $options['platformOptions']['version'] = $class->isVersioned && $class->versionField == $mapping['fieldName'] ? true : false; if (strtolower($columnType) == 'string' && $options['length'] === null) { $options['length'] = 255; } if (isset($mapping['precision'])) { $options['precision'] = $mapping['precision']; } if (isset($mapping['scale'])) { $options['scale'] = $mapping['scale']; } if (isset($mapping['default'])) { $options['default'] = $mapping['default']; } if (isset($mapping['columnDefinition'])) { $options['columnDefinition'] = $mapping['columnDefinition']; } if ($table->hasColumn($columnName)) { // required in some inheritence scenarios $table->changeColumn($columnName, $options); } else { $table->createColumn($columnName, $columnType, $options); } $isUnique = isset($mapping['unique']) ? $mapping['unique'] : false; if ($isUnique) { $table->addUniqueIndex(array($columnName)); } }