Ejemplo n.º 1
0
 protected function relateI18nTableToMainTable()
 {
     $table = $this->getTable();
     $i18nTable = $this->i18nTable;
     $pks = $this->getTable()->getPrimaryKey();
     if (count($pks) > 1) {
         throw new EngineException('The i18n behavior does not support tables with composite primary keys');
     }
     foreach ($pks as $column) {
         if (!$i18nTable->hasColumn($column->getName())) {
             $column = clone $column;
             $column->setAutoIncrement(false);
             $i18nTable->addColumn($column);
         }
     }
     if (in_array($table->getName(), $i18nTable->getForeignTableNames())) {
         return;
     }
     $fk = new ForeignKey();
     $fk->setForeignTableCommonName($table->getCommonName());
     $fk->setForeignSchemaName($table->getSchema());
     $fk->setDefaultJoin('LEFT JOIN');
     $fk->setOnDelete(ForeignKey::CASCADE);
     $fk->setOnUpdate(ForeignKey::NONE);
     foreach ($pks as $column) {
         $fk->addReference($column->getName(), $column->getName());
     }
     $i18nTable->addForeignKey($fk);
 }
 protected function addClosureColumn($name, Table $ct_table, Column $column)
 {
     $table = $this->getTable();
     $id_fieldname = $column->getName();
     $domain = $column->getDomain();
     if (!$ct_table->hasColumn($name)) {
         $column = new Column($name);
         $column->setDomain($domain);
         $column->setPrimaryKey(true);
         $ct_table->addColumn($column);
     } else {
         $column = $ct_table->getColumn($name);
     }
     $ct_tablename_normalized = str_replace('_', '', $ct_table->getName());
     $fk_name = $ct_tablename_normalized . '_' . $name . '_fk';
     if (!$ct_table->getColumnForeignKeys($name)) {
         $column_fk = new ForeignKey($fk_name);
         $column_fk->addReference($name, $table->getColumn($id_fieldname)->getName());
         $column_fk->setForeignTableCommonName($table->getName());
         $column_fk->setOnUpdate('cascade');
         $column_fk->setOnDelete('restrict');
         $ct_table->addForeignKey($column_fk);
     }
     $column_idx_name = $fk_name . '_idx';
     if (!$ct_table->hasIndex($column_idx_name)) {
         $column_idx = new Index($column_idx_name);
         $column_idx->addColumn(['name' => $column->getName()]);
         $ct_table->addIndex($column_idx);
     }
 }
 /**
  * Adds all columns, indexes, constraints and additional tables.
  */
 public function modifyTable()
 {
     $table = $this->getTable();
     $tableName = $table->getName();
     $foreignTableName = $this->getForeignTable();
     // enable reload on insert to force the model to load the trigger generated id(s)
     $table->setReloadOnInsert(true);
     $foreignIdColumnName = $foreignTableName . '_id';
     $compositeKeyColumnName = $foreignTableName . '_' . $tableName . '_id';
     if ($table->hasBehavior('concrete_inheritance')) {
         // we're a child in a concrete inheritance
         $parentTableName = $table->getBehavior('concrete_inheritance')->getParameter('extends');
         $parentTable = $table->getDatabase()->getTable($parentTableName);
         if ($parentTable->hasBehavior('\\' . __CLASS__)) {
             //we're a child of a concrete inheritance structure, so we're going to skip this
             //round here because this behavior has also been attached by the parent table.
             return;
         }
     }
     if ($table->hasColumn($foreignIdColumnName)) {
         $foreignIdColumn = $table->getColumn($foreignIdColumnName);
     } else {
         $foreignIdColumn = $table->addColumn(array('name' => $foreignIdColumnName, 'type' => 'integer', 'required' => true));
         $compositeKeyForeignKeyName = $tableName . '_FK_' . $foreignIdColumnName;
         $foreignKey = new ForeignKey($compositeKeyForeignKeyName);
         $foreignKey->addReference($foreignIdColumnName, 'id');
         $foreignKey->setForeignTableCommonName($foreignTableName);
         $foreignKey->setOnUpdate(ForeignKey::CASCADE);
         $foreignKey->setOnDelete(ForeignKey::CASCADE);
         $table->addForeignKey($foreignKey);
     }
     if ($table->hasColumn($compositeKeyColumnName)) {
         $compositeKeyColumn = $table->getColumn($compositeKeyColumnName);
     } else {
         $compositeKeyColumn = $table->addColumn(array('name' => $compositeKeyColumnName, 'type' => 'integer', 'required' => false));
     }
     $index = new Unique($tableName . '_UQ_' . $foreignIdColumnName . '_' . $compositeKeyColumnName);
     $index->addColumn($foreignIdColumn);
     $index->addColumn($compositeKeyColumn);
     $table->addUnique($index);
     $database = $table->getDatabase();
     $sequenceTableName = sprintf('%s_sequence', $foreignTableName);
     if (!$database->hasTable($sequenceTableName)) {
         $sequenceTable = $database->addTable(array('name' => $sequenceTableName, 'package' => $table->getPackage(), 'schema' => $table->getSchema(), 'namespace' => $table->getNamespace() ? '\\' . $table->getNamespace() : null, 'skipSql' => $table->isSkipSql()));
         $sequenceTable->addColumn(array('name' => 'table_name', 'type' => 'varchar', 'size' => 32, 'required' => true, 'primaryKey' => true));
         $sequenceTable->addColumn(array('name' => $foreignIdColumnName, 'type' => 'integer', 'required' => true, 'primaryKey' => true));
         $sequenceTable->addColumn(array('name' => $foreignTableName . '_max_sequence_id', 'type' => 'integer', 'required' => false, 'default' => null));
     }
 }
Ejemplo n.º 4
0
 protected function relateDelegateToMainTable($delegateTable, $mainTable)
 {
     $pks = $mainTable->getPrimaryKey();
     foreach ($pks as $column) {
         $mainColumnName = $column->getName();
         if (!$delegateTable->hasColumn($mainColumnName)) {
             $column = clone $column;
             $column->setAutoIncrement(false);
             $delegateTable->addColumn($column);
         }
     }
     // Add a one-to-one fk
     $fk = new ForeignKey();
     $fk->setForeignTableCommonName($mainTable->getCommonName());
     $fk->setForeignSchemaName($mainTable->getSchema());
     $fk->setDefaultJoin('LEFT JOIN');
     $fk->setOnDelete(ForeignKey::CASCADE);
     $fk->setOnUpdate(ForeignKey::NONE);
     foreach ($pks as $column) {
         $fk->addReference($column->getName(), $column->getName());
     }
     $delegateTable->addForeignKey($fk);
 }
 public function getForeignKeyDDL(ForeignKey $fk)
 {
     if ($fk->isSkipSql() || $fk->isPolymorphic()) {
         return;
     }
     $pattern = 'CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)';
     $script = sprintf($pattern, $this->quoteIdentifier($fk->getName()), $this->getColumnListDDL($fk->getLocalColumnObjects()), $this->quoteIdentifier($fk->getForeignTableName()), $this->getColumnListDDL($fk->getForeignColumnObjects()));
     if ($fk->hasOnUpdate() && $fk->getOnUpdate() != ForeignKey::SETNULL) {
         $script .= ' ON UPDATE ' . $fk->getOnUpdate();
     }
     if ($fk->hasOnDelete() && $fk->getOnDelete() != ForeignKey::SETNULL) {
         $script .= ' ON DELETE ' . $fk->getOnDelete();
     }
     return $script;
 }
Ejemplo n.º 6
0
 protected static function getRefRelatedBySuffix(ForeignKey $fk)
 {
     $relCol = '';
     foreach ($fk->getLocalForeignMapping() as $localColumnName => $foreignColumnName) {
         $localTable = $fk->getTable();
         $localColumn = $localTable->getColumn($localColumnName);
         if (!$localColumn) {
             throw new RuntimeException(sprintf('Could not fetch column: %s in table %s.', $localColumnName, $localTable->getName()));
         }
         $foreignKeysToForeignTable = $localTable->getForeignKeysReferencingTable($fk->getForeignTableName());
         if ($fk->getForeignTableName() == $fk->getTableName()) {
             // self referential foreign key
             $relCol .= $fk->getForeignTable()->getColumn($foreignColumnName)->getPhpName();
             if (count($foreignKeysToForeignTable) > 1) {
                 // several self-referential foreign keys
                 $relCol .= array_search($fk, $foreignKeysToForeignTable);
             }
         } elseif (count($foreignKeysToForeignTable) > 1 || count($fk->getForeignTable()->getForeignKeysReferencingTable($fk->getTableName())) > 0) {
             // several foreign keys to the same table, or symmetrical foreign key in foreign table
             $relCol .= $localColumn->getPhpName();
         }
     }
     if (!empty($relCol)) {
         $relCol = 'RelatedBy' . $relCol;
     }
     return $relCol;
 }
 public function getForeignKeyDDL(ForeignKey $fk)
 {
     if ($fk->isSkipSql() || !$this->foreignKeySupport) {
         return;
     }
     $pattern = "FOREIGN KEY (%s) REFERENCES %s (%s)";
     $script = sprintf($pattern, $this->getColumnListDDL($fk->getLocalColumns()), $this->quoteIdentifier($fk->getForeignTableName()), $this->getColumnListDDL($fk->getForeignColumns()));
     if ($fk->hasOnUpdate()) {
         $script .= "\n    ON UPDATE " . $fk->getOnUpdate();
     }
     if ($fk->hasOnDelete()) {
         $script .= "\n    ON DELETE " . $fk->getOnDelete();
     }
     return $script;
 }
Ejemplo n.º 8
0
 protected function addForeignKeys(Table $table)
 {
     $database = $table->getDatabase();
     $stmt = $this->dbh->query('PRAGMA foreign_key_list("' . $table->getName() . '")');
     $lastId = null;
     while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
         if ($lastId !== $row['id']) {
             $fk = new ForeignKey();
             $onDelete = $row['on_delete'];
             if ($onDelete && 'NO ACTION' !== $onDelete) {
                 $fk->setOnDelete($onDelete);
             }
             $onUpdate = $row['on_update'];
             if ($onUpdate && 'NO ACTION' !== $onUpdate) {
                 $fk->setOnUpdate($onUpdate);
             }
             $foreignTable = $database->getTable($row['table'], true);
             if (!$foreignTable) {
                 continue;
             }
             $table->addForeignKey($fk);
             $fk->setForeignTableCommonName($foreignTable->getCommonName());
             if ($table->guessSchemaName() != $foreignTable->guessSchemaName()) {
                 $fk->setForeignSchemaName($foreignTable->guessSchemaName());
             }
             $lastId = $row['id'];
         }
         $fk->addReference($row['from'], $row['to']);
     }
 }
Ejemplo n.º 9
0
 protected function addRefFkScheduledForDeletionAttribute(&$script, ForeignKey $refFK)
 {
     $className = $this->getClassNameFromTable($refFK->getTable());
     $fkName = lcfirst($this->getRefFKPhpNameAffix($refFK, true));
     $script .= "\n    /**\n     * An array of objects scheduled for deletion.\n     * @var ObjectCollection|{$className}[]\n     */\n    protected \${$fkName}ScheduledForDeletion = null;\n";
 }
 public function modifyTable()
 {
     $table = $this->getTable();
     $parentTable = $this->getParentTable();
     if ($this->isCopyData()) {
         // tell the parent table that it has a descendant
         if (!$parentTable->hasBehavior('concrete_inheritance_parent')) {
             $parentBehavior = new ConcreteInheritanceParentBehavior();
             $parentBehavior->setName('concrete_inheritance_parent');
             $parentBehavior->addParameter(array('name' => 'descendant_column', 'value' => $this->getParameter('descendant_column')));
             $parentTable->addBehavior($parentBehavior);
             // The parent table's behavior modifyTable() must be executed before this one
             $parentBehavior->getTableModifier()->modifyTable();
             $parentBehavior->setTableModified(true);
         }
     }
     // Add the columns of the parent table
     foreach ($parentTable->getColumns() as $column) {
         if ($column->getName() == $this->getParameter('descendant_column')) {
             continue;
         }
         if ($table->hasColumn($column->getName())) {
             continue;
         }
         $copiedColumn = clone $column;
         if ($column->isAutoIncrement() && $this->isCopyData()) {
             $copiedColumn->setAutoIncrement(false);
         }
         $table->addColumn($copiedColumn);
         if ($column->isPrimaryKey() && $this->isCopyData()) {
             $fk = new ForeignKey();
             $fk->setForeignTableCommonName($column->getTable()->getCommonName());
             $fk->setForeignSchemaName($column->getTable()->getSchema());
             $fk->setOnDelete('CASCADE');
             $fk->setOnUpdate(null);
             $fk->addReference($copiedColumn, $column);
             $fk->isParentChild = true;
             $table->addForeignKey($fk);
         }
     }
     // add the foreign keys of the parent table
     foreach ($parentTable->getForeignKeys() as $fk) {
         $copiedFk = clone $fk;
         $copiedFk->setName('');
         $copiedFk->setRefPhpName('');
         $this->getTable()->addForeignKey($copiedFk);
     }
     // add the indices of the parent table
     foreach ($parentTable->getIndices() as $index) {
         $copiedIndex = clone $index;
         $copiedIndex->setName('');
         $this->getTable()->addIndex($copiedIndex);
     }
     // add the unique indices of the parent table
     foreach ($parentTable->getUnices() as $unique) {
         $copiedUnique = clone $unique;
         $copiedUnique->setName('');
         $this->getTable()->addUnique($copiedUnique);
     }
     // add the Behaviors of the parent table
     foreach ($parentTable->getBehaviors() as $behavior) {
         if ($behavior->getName() == 'concrete_inheritance_parent' || $behavior->getName() == 'concrete_inheritance') {
             continue;
         }
         //validate behavior. If validate behavior already exists, clone only rules from parent
         if ('validate' === $behavior->getName() && $table->hasBehavior('validate')) {
             $table->getBehavior('validate')->mergeParameters($behavior->getParameters());
             continue;
         }
         $copiedBehavior = clone $behavior;
         $copiedBehavior->setTableModified(false);
         $this->getTable()->addBehavior($copiedBehavior);
     }
 }
Ejemplo n.º 11
0
 /**
  * @param        string &$script The script will be modified in this method.
  * @param        ForeignKey $refFK
  * @param        ForeignKey $crossFK
  */
 protected function addCrossFKDoAdd(&$script, ForeignKey $refFK, ForeignKey $crossFK)
 {
     $relatedObjectClassName = $this->getFKPhpNameAffix($crossFK, $plural = false);
     // lcfirst() doesn't exist in PHP < 5.3
     $lowerRelatedObjectClassName = $relatedObjectClassName;
     $lowerRelatedObjectClassName[0] = strtolower($lowerRelatedObjectClassName[0]);
     $joinedTableObjectBuilder = $this->getNewObjectBuilder($refFK->getTable());
     $className = $joinedTableObjectBuilder->getObjectClassname();
     $tblFK = $refFK->getTable();
     $foreignObjectName = '$' . $tblFK->getStudlyPhpName();
     $script .= "\n    /**\n     * @param    {$relatedObjectClassName} \${$lowerRelatedObjectClassName} The {$lowerRelatedObjectClassName} object to add.\n     */\n    protected function doAdd{$relatedObjectClassName}(\${$lowerRelatedObjectClassName})\n    {\n        {$foreignObjectName} = new {$className}();\n        {$foreignObjectName}->set{$relatedObjectClassName}(\${$lowerRelatedObjectClassName});\n        \$this->add{$className}({$foreignObjectName});\n    }\n";
 }
Ejemplo n.º 12
0
 /**
  * Appends the generated <foreign-key> XML node to its parent node.
  *
  * @param ForeignKey $foreignKey The ForeignKey model instance
  * @param \DOMNode   $parentNode The parent DOMNode object
  */
 private function appendForeignKeyNode(ForeignKey $foreignKey, \DOMNode $parentNode)
 {
     $foreignKeyNode = $parentNode->appendChild($this->document->createElement('foreign-key'));
     $foreignKeyNode->setAttribute('foreignTable', $foreignKey->getForeignTableCommonName());
     if ($schema = $foreignKey->getForeignSchemaName()) {
         $foreignKeyNode->setAttribute('foreignSchema', $schema);
     }
     $foreignKeyNode->setAttribute('name', $foreignKey->getName());
     if ($phpName = $foreignKey->getPhpName()) {
         $foreignKeyNode->setAttribute('phpName', $phpName);
     }
     if ($refPhpName = $foreignKey->getRefPhpName()) {
         $foreignKeyNode->setAttribute('refPhpName', $refPhpName);
     }
     if ($defaultJoin = $foreignKey->getDefaultJoin()) {
         $foreignKeyNode->setAttribute('defaultJoin', $defaultJoin);
     }
     if ($onDeleteBehavior = $foreignKey->getOnDelete()) {
         $foreignKeyNode->setAttribute('onDelete', $onDeleteBehavior);
     }
     if ($onUpdateBehavior = $foreignKey->getOnUpdate()) {
         $foreignKeyNode->setAttribute('onUpdate', $onUpdateBehavior);
     }
     for ($i = 0, $size = count($foreignKey->getLocalColumns()); $i < $size; $i++) {
         $refNode = $foreignKeyNode->appendChild($this->document->createElement('reference'));
         $refNode->setAttribute('local', $foreignKey->getLocalColumnName($i));
         $refNode->setAttribute('foreign', $foreignKey->getForeignColumnName($i));
     }
     foreach ($foreignKey->getVendorInformation() as $vendorInformation) {
         $this->appendVendorInformationNode($vendorInformation, $foreignKeyNode);
     }
 }
 private function addSnapshotTable()
 {
     $table = $this->getTable();
     $primaryKeyColumn = $table->getFirstPrimaryKeyColumn();
     $database = $table->getDatabase();
     $snapshotTableName = $this->getParameter(self::PARAMETER_SNAPSHOT_TABLE) ?: $this->getDefaultSnapshotTableName();
     if ($database->hasTable($snapshotTableName)) {
         $this->snapshotTable = $database->getTable($snapshotTableName);
         return;
     }
     $snapshotTable = $database->addTable(['name' => $snapshotTableName, 'phpName' => $this->getParameter(self::PARAMETER_SNAPSHOT_PHPNAME), 'package' => $table->getPackage(), 'schema' => $table->getSchema(), 'namespace' => $table->getNamespace() ? '\\' . $table->getNamespace() : null]);
     $addSnapshotAt = true;
     $hasTimestampableBehavior = 0 < count(array_filter($database->getBehaviors(), function (Behavior $behavior) {
         return 'timestampable' === $behavior->getName();
     }));
     if ($hasTimestampableBehavior) {
         $addSnapshotAt = false;
         $timestampableBehavior = clone $database->getBehavior('timestampable');
         $timestampableBehavior->setParameters(array_merge($timestampableBehavior->getParameters(), ['create_column' => $this->getParameter(self::PARAMETER_SNAPSHOT_AT_COLUMN), 'disable_updated_at' => 'true']));
         $snapshotTable->addBehavior($timestampableBehavior);
     }
     $snapshotTable->isSnapshotTable = true;
     $idColumn = $snapshotTable->addColumn(['name' => 'id', 'type' => 'INTEGER']);
     $idColumn->setAutoIncrement(true);
     $idColumn->setPrimaryKey(true);
     $idColumn->setNotNull(true);
     $columns = $table->getColumns();
     foreach ($columns as $column) {
         if ($column->isPrimaryKey()) {
             continue;
         }
         $columnInSnapshotTable = clone $column;
         $columnInSnapshotTable->setNotNull(false);
         if ($columnInSnapshotTable->hasReferrers()) {
             $columnInSnapshotTable->clearReferrers();
         }
         if ($columnInSnapshotTable->isAutoincrement()) {
             $columnInSnapshotTable->setAutoIncrement(false);
         }
         $snapshotTable->addColumn($columnInSnapshotTable);
     }
     $foreignKeyColumn = $snapshotTable->addColumn(['name' => $this->getParameter(self::PARAMETER_REFERENCE_COLUMN), 'type' => $primaryKeyColumn->getType(), 'size' => $primaryKeyColumn->getSize()]);
     $index = new Index();
     $index->setName($this->getParameter(self::PARAMETER_REFERENCE_COLUMN));
     if ($primaryKeyColumn->getSize()) {
         $index->addColumn(['name' => $this->getParameter(self::PARAMETER_REFERENCE_COLUMN), 'size' => $primaryKeyColumn->getSize()]);
     } else {
         $index->addColumn(['name' => $this->getParameter(self::PARAMETER_REFERENCE_COLUMN)]);
     }
     $snapshotTable->addIndex($index);
     $foreignKey = new ForeignKey();
     $foreignKey->setName(vsprintf('fk_%s_%s', [$snapshotTable->getOriginCommonName(), $this->getParameter(self::PARAMETER_REFERENCE_COLUMN)]));
     $foreignKey->setOnUpdate('CASCADE');
     $foreignKey->setOnDelete('SET NULL');
     $foreignKey->setForeignTableCommonName($this->getTable()->getCommonName());
     $foreignKey->addReference($foreignKeyColumn, $primaryKeyColumn);
     $snapshotTable->addForeignKey($foreignKey);
     if ($this->getParameter(self::PARAMETER_LOG_SNAPSHOT_AT) == 'true' && $addSnapshotAt) {
         $snapshotTable->addColumn(['name' => $this->getParameter(self::PARAMETER_SNAPSHOT_AT_COLUMN), 'type' => 'TIMESTAMP']);
     }
     $indices = $table->getIndices();
     foreach ($indices as $index) {
         $copiedIndex = clone $index;
         $snapshotTable->addIndex($copiedIndex);
     }
     // copy unique indices to indices
     // see https://github.com/propelorm/Propel/issues/175 for details
     $unices = $table->getUnices();
     foreach ($unices as $unique) {
         $index = new Index();
         $index->setName($unique->getName());
         $columns = $unique->getColumns();
         foreach ($columns as $columnName) {
             if ($size = $unique->getColumnSize($columnName)) {
                 $index->addColumn(['name' => $columnName, 'size' => $size]);
             } else {
                 $index->addColumn(['name' => $columnName]);
             }
         }
         $snapshotTable->addIndex($index);
     }
     $behaviors = $database->getBehaviors();
     foreach ($behaviors as $behavior) {
         $behavior->modifyDatabase();
     }
     $this->snapshotTable = $snapshotTable;
 }
 public function providerForTestGetForeignKeysDDL()
 {
     $db = new Database();
     $db->setIdentifierQuoting(true);
     $table1 = new Table('foo');
     $db->addTable($table1);
     $column1 = new Column('bar_id');
     $column1->getDomain()->copy(new Domain('FOOTYPE'));
     $table1->addColumn($column1);
     $table2 = new Table('bar');
     $db->addTable($table2);
     $column2 = new Column('id');
     $column2->getDomain()->copy(new Domain('BARTYPE'));
     $table2->addColumn($column2);
     $fk = new ForeignKey('foo_bar_fk');
     $fk->setForeignTableCommonName('bar');
     $fk->addReference($column1, $column2);
     $fk->setOnDelete('CASCADE');
     $table1->addForeignKey($fk);
     $column3 = new Column('baz_id');
     $column3->getDomain()->copy(new Domain('BAZTYPE'));
     $table1->addColumn($column3);
     $table3 = new Table('baz');
     $db->addTable($table3);
     $column4 = new Column('id');
     $column4->getDomain()->copy(new Domain('BAZTYPE'));
     $table3->addColumn($column4);
     $fk = new ForeignKey('foo_baz_fk');
     $fk->setForeignTableCommonName('baz');
     $fk->addReference($column3, $column4);
     $fk->setOnDelete('SETNULL');
     $table1->addForeignKey($fk);
     return array(array($table1));
 }
 /**
  * Adds a relation from logTable to origin table.
  *
  * @param Table $logTable
  */
 protected function addForeignKey(Table $logTable)
 {
     $table = $this->getTable();
     if ($table->getForeignKeysReferencingTable($table->getName())) {
         //if already a foreignKey exist to origin table then don't add a second.
         return;
     }
     // create the foreign key
     $fk = new ForeignKey();
     $fk->setForeignTableCommonName($table->getCommonName());
     $fk->setForeignSchemaName($table->getSchema());
     $fk->setPhpName('Origin');
     $fk->setOnDelete('CASCADE');
     $fk->setOnUpdate('CASCADE');
     foreach ($table->getPrimaryKey() as $column) {
         $fk->addReference($logTable->getColumn($column->getName()), $column);
     }
     $logTable->addForeignKey($fk);
 }
Ejemplo n.º 16
0
$fkAuthorPost->setDefaultJoin('Criteria::LEFT_JOIN');
$fkAuthorPost->setOnDelete('CASCADE');
$fkCategoryPost = new ForeignKey('fk_post_has_category');
$fkCategoryPost->addReference('category_id', 'id');
$fkCategoryPost->setForeignTableCommonName('blog_category');
$fkCategoryPost->setRefPhpName('Posts');
$fkCategoryPost->setPhpName('Category');
$fkCategoryPost->setDefaultJoin('Criteria::INNER_JOIN');
$fkCategoryPost->setOnDelete('SETNULL');
$fkPostTag = new ForeignKey('fk_post_has_tags');
$fkPostTag->addReference('post_id', 'id');
$fkPostTag->setForeignTableCommonName('blog_post');
$fkPostTag->setPhpName('Post');
$fkPostTag->setDefaultJoin('Criteria::LEFT_JOIN');
$fkPostTag->setOnDelete('CASCADE');
$fkTagPost = new ForeignKey('fk_tag_has_posts');
$fkTagPost->addReference('tag_id', 'id');
$fkTagPost->setForeignTableCommonName('blog_tag');
$fkTagPost->setPhpName('Tag');
$fkTagPost->setDefaultJoin('Criteria::LEFT_JOIN');
$fkTagPost->setOnDelete('CASCADE');
/* Regular Indexes */
$pageContentFulltextIdx = new Index('page_content_fulltext_idx');
$pageContentFulltextIdx->setColumns([['name' => 'content']]);
$pageContentFulltextIdx->addVendorInfo(new VendorInfo('mysql', ['Index_type' => 'FULLTEXT']));
/* Unique Indexes */
$authorUsernameUnique = new Unique('author_password_unique_idx');
$authorUsernameUnique->setColumns([['name' => 'username', 'size' => '8']]);
/* Behaviors */
$timestampableBehavior = new TimestampableBehavior();
$timestampableBehavior->setName('timestampable');
 public function getReferrerVersionsColumn(ForeignKey $fk)
 {
     $fkTableName = $fk->getTable()->getName();
     $fkIdsColumnName = $fkTableName . '_versions';
     return $this->versionTable->getColumn($fkIdsColumnName);
 }
Ejemplo n.º 18
0
 public function getForeignKeyDDL(ForeignKey $fk)
 {
     $pattern = "\n-- SQLite does not support foreign keys; this is just for reference\n-- FOREIGN KEY (%s) REFERENCES %s (%s)\n";
     return sprintf($pattern, $this->getColumnListDDL($fk->getLocalColumns()), $fk->getForeignTableName(), $this->getColumnListDDL($fk->getForeignColumns()));
 }
Ejemplo n.º 19
0
 /**
  * Load foreign keys for this table.
  *
  * @param Table $table The Table model class to add FKs to
  */
 protected function addForeignKeys(Table $table)
 {
     // local store to avoid duplicates
     $foreignKeys = array();
     /* @var StatementInterface $stmt */
     $stmt = $this->dbh->query("SELECT CONSTRAINT_NAME, DELETE_RULE, R_CONSTRAINT_NAME FROM USER_CONSTRAINTS WHERE CONSTRAINT_TYPE = 'R' AND TABLE_NAME = '" . $table->getName() . "'");
     while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
         // Local reference
         /* @var StatementInterface $stmt2 */
         $stmt2 = $this->dbh->query("SELECT COLUMN_NAME FROM USER_CONS_COLUMNS WHERE CONSTRAINT_NAME = '" . $row['CONSTRAINT_NAME'] . "' AND TABLE_NAME = '" . $table->getName() . "'");
         $localReferenceInfo = $stmt2->fetch(\PDO::FETCH_ASSOC);
         // Foreign reference
         $stmt2 = $this->dbh->query("SELECT TABLE_NAME, COLUMN_NAME FROM USER_CONS_COLUMNS WHERE CONSTRAINT_NAME = '" . $row['R_CONSTRAINT_NAME'] . "'");
         $foreignReferenceInfo = $stmt2->fetch(\PDO::FETCH_ASSOC);
         if (!isset($foreignKeys[$row['CONSTRAINT_NAME']])) {
             $fk = new ForeignKey($row['CONSTRAINT_NAME']);
             $fk->setForeignTableCommonName($foreignReferenceInfo['TABLE_NAME']);
             $onDelete = 'NO ACTION' === $row['DELETE_RULE'] ? 'NONE' : $row['DELETE_RULE'];
             $fk->setOnDelete($onDelete);
             $fk->setOnUpdate($onDelete);
             $fk->addReference(array('local' => $localReferenceInfo['COLUMN_NAME'], 'foreign' => $foreignReferenceInfo['COLUMN_NAME']));
             $table->addForeignKey($fk);
             $foreignKeys[$row['CONSTRAINT_NAME']] = $fk;
         }
     }
 }
Ejemplo n.º 20
0
 /**
  * Adds a new foreign key to this table.
  *
  * @param ForeignKey|array
  * @return ForeignKey
  */
 public function addForeignKey($fkdata)
 {
     if ($fkdata instanceof ForeignKey) {
         $fk = $fkdata;
         $fk->setTable($this);
         $this->foreignKeys[] = $fk;
         if (!in_array($fk->getForeignTableName(), $this->foreignTableNames)) {
             $this->foreignTableNames[] = $fk->getForeignTableName();
         }
         return $fk;
     }
     $fk = new ForeignKey();
     $fk->setTable($this);
     $fk->loadMapping($fkdata);
     return $this->addForeignKey($fk);
 }
Ejemplo n.º 21
0
 /**
  * A utility function to create a new foreign key
  * from attrib and add it to this table.
  */
 public function addForeignKey($fkdata)
 {
     if ($fkdata instanceof ForeignKey) {
         $fk = $fkdata;
         $fk->setTable($this);
         $this->foreignKeys[] = $fk;
         if ($this->foreignTableNames === null) {
             $this->foreignTableNames = array();
         }
         if (!in_array($fk->getForeignTableName(), $this->foreignTableNames)) {
             $this->foreignTableNames[] = $fk->getForeignTableName();
         }
         return $fk;
     } else {
         $fk = new ForeignKey();
         $fk->setTable($this);
         $fk->loadFromXML($fkdata);
         return $this->addForeignKey($fk);
     }
 }
Ejemplo n.º 22
0
    public function testToString()
    {
        $tableA = new Table('A');
        $tableB = new Table('B');
        $diff = new TableDiff($tableA, $tableB);
        $diff->addAddedColumn('id', new Column('id', 'integer'));
        $diff->addRemovedColumn('category_id', new Column('category_id', 'integer'));
        $colFoo = new Column('foo', 'integer');
        $colBar = new Column('bar', 'integer');
        $tableA->addColumn($colFoo);
        $tableA->addColumn($colBar);
        $diff->addRenamedColumn($colFoo, $colBar);
        $columnDiff = new ColumnDiff($colFoo, $colBar);
        $diff->addModifiedColumn('foo', $columnDiff);
        $fk = new ForeignKey('category');
        $fk->setTable($tableA);
        $fk->setForeignTableCommonName('B');
        $fk->addReference('category_id', 'id');
        $fkChanged = clone $fk;
        $fkChanged->setForeignTableCommonName('C');
        $fkChanged->addReference('bla', 'id2');
        $fkChanged->setOnDelete('cascade');
        $fkChanged->setOnUpdate('cascade');
        $diff->addAddedFk('category', $fk);
        $diff->addModifiedFk('category', $fk, $fkChanged);
        $diff->addRemovedFk('category', $fk);
        $index = new Index('test_index');
        $index->setTable($tableA);
        $index->setColumns([$colFoo]);
        $indexChanged = clone $index;
        $indexChanged->setColumns([$colBar]);
        $diff->addAddedIndex('test_index', $index);
        $diff->addModifiedIndex('test_index', $index, $indexChanged);
        $diff->addRemovedIndex('test_index', $index);
        $string = (string) $diff;
        $expected = '  A:
    addedColumns:
      - id
    removedColumns:
      - category_id
    modifiedColumns:
      A.FOO:
        modifiedProperties:
    renamedColumns:
      foo: bar
    addedIndices:
      - test_index
    removedIndices:
      - test_index
    modifiedIndices:
      - test_index
    addedFks:
      - category
    removedFks:
      - category
    modifiedFks:
      category:
          localColumns: from ["category_id"] to ["category_id","bla"]
          foreignColumns: from ["id"] to ["id","id2"]
          onUpdate: from  to CASCADE
          onDelete: from  to CASCADE
';
        $this->assertEquals($expected, $string);
    }
Ejemplo n.º 23
0
 /**
  * Adds the useFkQuery method for this object.
  * @param string     &$script The script will be modified in this method.
  * @param ForeignKey $fk
  */
 protected function addUseRefFkQuery(&$script, ForeignKey $fk)
 {
     $fkTable = $this->getTable()->getDatabase()->getTable($fk->getTableName());
     $fkQueryBuilder = $this->getNewStubQueryBuilder($fkTable);
     $queryClass = $this->getClassNameFromBuilder($fkQueryBuilder, true);
     $relationName = $this->getRefFKPhpNameAffix($fk);
     $joinType = $this->getJoinType($fk);
     $this->addUseRelatedQuery($script, $fkTable, $queryClass, $relationName, $joinType);
 }
 public function testCompareSort()
 {
     $c1 = new Column('Foo');
     $c2 = new Column('Bar');
     $c3 = new Column('Baz');
     $c4 = new Column('Faz');
     $fk1 = new ForeignKey();
     $fk1->addReference($c1, $c3);
     $fk1->addReference($c2, $c4);
     $t1 = new Table('Baz');
     $t1->addForeignKey($fk1);
     $fk2 = new ForeignKey();
     $fk2->addReference($c2, $c4);
     $fk2->addReference($c1, $c3);
     $t2 = new Table('Baz');
     $t2->addForeignKey($fk2);
     $this->assertFalse(PropelForeignKeyComparator::computeDiff($fk1, $fk2));
 }
Ejemplo n.º 25
0
 public function getForeignKeyDDL(ForeignKey $fk)
 {
     if ($fk->isSkipSql() || $fk->isPolymorphic()) {
         return;
     }
     $pattern = "CONSTRAINT %s\n    FOREIGN KEY (%s) REFERENCES %s (%s)";
     $script = sprintf($pattern, $this->quoteIdentifier($fk->getName()), $this->getColumnListDDL($fk->getLocalColumnObjects()), $this->quoteIdentifier($fk->getForeignTableName()), $this->getColumnListDDL($fk->getForeignColumnObjects()));
     if ($fk->hasOnDelete()) {
         $script .= "\n    ON DELETE " . $fk->getOnDelete();
     }
     return $script;
 }
 public function testCompareModifiedFks()
 {
     $db1 = new Database();
     $db1->setPlatform($this->platform);
     $c1 = new Column('Foo');
     $c2 = new Column('Bar');
     $fk1 = new ForeignKey();
     $fk1->addReference($c1, $c2);
     $t1 = new Table('Baz');
     $t1->addForeignKey($fk1);
     $db1->addTable($t1);
     $t1->doNaming();
     $db2 = new Database();
     $db2->setPlatform($this->platform);
     $c3 = new Column('Foo');
     $c4 = new Column('Bar2');
     $fk2 = new ForeignKey();
     $fk2->addReference($c3, $c4);
     $t2 = new Table('Baz');
     $t2->addForeignKey($fk2);
     $db2->addTable($t2);
     $t2->doNaming();
     $tc = new TableComparator();
     $tc->setFromTable($t1);
     $tc->setToTable($t2);
     $nbDiffs = $tc->compareForeignKeys();
     $tableDiff = $tc->getTableDiff();
     $this->assertEquals(1, $nbDiffs);
     $this->assertEquals(1, count($tableDiff->getModifiedFks()));
     $this->assertEquals(array('Baz_FK_1' => array($fk1, $fk2)), $tableDiff->getModifiedFks());
 }
Ejemplo n.º 27
0
 public function getDropForeignKeyDDL(ForeignKey $fk)
 {
     if (!$this->supportsForeignKeys($fk->getTable())) {
         return '';
     }
     if ($fk->isSkipSql()) {
         return;
     }
     $pattern = "\nALTER TABLE %s DROP FOREIGN KEY %s;\n";
     return sprintf($pattern, $this->quoteIdentifier($fk->getTable()->getName()), $this->quoteIdentifier($fk->getName()));
 }
 /**
  * Load foreign keys for this table.
  */
 protected function addForeignKeys(Table $table, $oid)
 {
     $database = $table->getDatabase();
     $stmt = $this->dbh->prepare("SELECT\n            conname,\n            confupdtype,\n            confdeltype,\n            CASE nl.nspname WHEN 'public' THEN cl.relname ELSE nl.nspname||'.'||cl.relname END as fktab,\n                array_agg(DISTINCT a2.attname) AS fkcols,\n                CASE nr.nspname WHEN 'public' THEN cr.relname ELSE nr.nspname||'.'||cr.relname END as reftab,\n                    array_agg(DISTINCT a1.attname) AS refcols\n                    FROM pg_constraint ct\n                    JOIN pg_class cl ON cl.oid=conrelid\n                    JOIN pg_class cr ON cr.oid=confrelid\n                    JOIN pg_namespace nl ON nl.oid = cl.relnamespace\n                    JOIN pg_namespace nr ON nr.oid = cr.relnamespace\n                    LEFT JOIN pg_catalog.pg_attribute a1 ON a1.attrelid = ct.confrelid\n                    LEFT JOIN pg_catalog.pg_attribute a2 ON a2.attrelid = ct.conrelid\n                    WHERE\n                    contype='f'\n                    AND conrelid = ?\n                    AND a2.attnum = ANY (ct.conkey)\n                    AND a1.attnum = ANY (ct.confkey)\n                    GROUP BY conname, confupdtype, confdeltype, fktab, reftab\n                    ORDER BY conname");
     $stmt->bindValue(1, $oid);
     $stmt->execute();
     $foreignKeys = array();
     while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
         $name = $row['conname'];
         $localTable = $row['fktab'];
         $localColumns = explode(',', trim($row['fkcols'], '{}'));
         $foreignTableName = $row['reftab'];
         $foreignColumns = explode(',', trim($row['refcols'], '{}'));
         // On Update
         switch ($row['confupdtype']) {
             case 'c':
                 $onupdate = ForeignKey::CASCADE;
                 break;
             case 'd':
                 $onupdate = ForeignKey::SETDEFAULT;
                 break;
             case 'n':
                 $onupdate = ForeignKey::SETNULL;
                 break;
             case 'r':
                 $onupdate = ForeignKey::RESTRICT;
                 break;
             default:
             case 'a':
                 // NOACTION is the postgresql default
                 $onupdate = ForeignKey::NONE;
                 break;
         }
         // On Delete
         switch ($row['confdeltype']) {
             case 'c':
                 $ondelete = ForeignKey::CASCADE;
                 break;
             case 'd':
                 $ondelete = ForeignKey::SETDEFAULT;
                 break;
             case 'n':
                 $ondelete = ForeignKey::SETNULL;
                 break;
             case 'r':
                 $ondelete = ForeignKey::RESTRICT;
                 break;
             default:
             case 'a':
                 // NOACTION is the postgresql default
                 $ondelete = ForeignKey::NONE;
                 break;
         }
         $foreignTable = $database->getTable($foreignTableName);
         $localTable = $database->getTable($localTable);
         if (!$foreignTable) {
             continue;
         }
         if (!isset($foreignKeys[$name])) {
             $fk = new ForeignKey($name);
             $fk->setForeignTableCommonName($foreignTable->getCommonName());
             if ($table->guessSchemaName() != $foreignTable->guessSchemaName()) {
                 $fk->setForeignSchemaName($foreignTable->getSchema());
             }
             $fk->setOnDelete($ondelete);
             $fk->setOnUpdate($onupdate);
             $table->addForeignKey($fk);
             $foreignKeys[$name] = $fk;
         }
         $max = count($localColumns);
         for ($i = 0; $i < $max; $i++) {
             $foreignKeys[$name]->addReference($localTable->getColumn($localColumns[$i]), $foreignTable->getColumn($foreignColumns[$i]));
         }
     }
 }
Ejemplo n.º 29
0
 /**
  * Compute the difference between two Foreign key objects
  *
  * @param ForeignKey $fromFk
  * @param ForeignKey $toFk
  *
  * @param boolean $caseInsensitive Whether the comparison is case insensitive.
  *                                 False by default.
  *
  * @return boolean false if the two fks are similar, true if they have differences
  */
 public static function computeDiff(ForeignKey $fromFk, ForeignKey $toFk, $caseInsensitive = false)
 {
     // Check for differences in local and remote table
     $test = $caseInsensitive ? strtolower($fromFk->getTableName()) != strtolower($toFk->getTableName()) : $fromFk->getTableName() != $toFk->getTableName();
     if ($test) {
         return true;
     }
     $test = $caseInsensitive ? strtolower($fromFk->getForeignTableName()) != strtolower($toFk->getForeignTableName()) : $fromFk->getForeignTableName() != $toFk->getForeignTableName();
     if ($test) {
         return true;
     }
     // compare columns
     $fromFkLocalColumns = $fromFk->getLocalColumns();
     sort($fromFkLocalColumns);
     $toFkLocalColumns = $toFk->getLocalColumns();
     sort($toFkLocalColumns);
     if (array_map('strtolower', $fromFkLocalColumns) != array_map('strtolower', $toFkLocalColumns)) {
         return true;
     }
     $fromFkForeignColumns = $fromFk->getForeignColumns();
     sort($fromFkForeignColumns);
     $toFkForeignColumns = $toFk->getForeignColumns();
     sort($toFkForeignColumns);
     if (array_map('strtolower', $fromFkForeignColumns) != array_map('strtolower', $toFkForeignColumns)) {
         return true;
     }
     // compare on
     if ($fromFk->normalizeFKey($fromFk->getOnUpdate()) != $toFk->normalizeFKey($toFk->getOnUpdate())) {
         return true;
     }
     if ($fromFk->normalizeFKey($fromFk->getOnDelete()) != $toFk->normalizeFKey($toFk->getOnDelete())) {
         return true;
     }
     // compare skipSql
     if ($fromFk->isSkipSql() != $toFk->isSkipSql()) {
         return true;
     }
     return false;
 }
Ejemplo n.º 30
0
 /**
  * Adds a new foreign key to this table.
  *
  * @param  ForeignKey|array $foreignKey The foreign key mapping
  * @return ForeignKey
  */
 public function addForeignKey($foreignKey)
 {
     if ($foreignKey instanceof ForeignKey) {
         $fk = $foreignKey;
         $fk->setTable($this);
         $name = $fk->getPhpName() ?: $fk->getName();
         if (isset($this->foreignKeysByName[$name])) {
             throw new EngineException(sprintf('Foreign key "%s" declared twice in table "%s". Please specify a different php name!', $name, $this->getName()));
         }
         $this->foreignKeys[] = $fk;
         $this->foreignKeysByName[$name] = $fk;
         if (!in_array($fk->getForeignTableName(), $this->foreignTableNames)) {
             $this->foreignTableNames[] = $fk->getForeignTableName();
         }
         return $fk;
     }
     $fk = new ForeignKey(isset($foreignKey['name']) ? $foreignKey['name'] : null);
     $fk->setTable($this);
     $fk->loadMapping($foreignKey);
     return $this->addForeignKey($fk);
 }