/** * Execute an alteration query of the pattern of the database according to setted parameters * * @return object result of the query */ public function alter() { if (!DB::getAlterSchema()) { return; } $new = false; # Check if table doesn't exists if (!Schema::hasTable($this->getTable())) { # Alter database $this->query(DB::SQL()::CREATE_TABLE($this->getTable(), [$this->SQL_column($this->schema)])); # Update table schema Schema::addTable($this->getTable()); Schema::getTable($this->getTable())->addColumn(clone $this->schema); $new = true; } # Check if column doesn't exists if (!$this->hasColumn($this->schema->getName())) { $this->query(DB::SQL()::ADD_COLUMN($this->getTable(), $this->SQL_column($this->schema))); # Update Schema Schema::getTable($this->getTable())->addColumn(clone $this->schema); $new = true; } # Actual schema $a = Schema::getTable($this->getTable())->getColumn($this->schema->getName()); if ($new) { $a->setIndex(null); $a->setForeign('', ''); } # New schema $n = $this->schema; # Update schema self::$tables[$this->getTable()]->setColumn($n); /* print_r("DB:"); print_r($a); print_r("PHP:"); print_r($n); */ $dropped_foreign = []; # Check if there is any difference between actual schema and new if (!$n->equals($a)) { # Drop X Primary key if # Actual: primary, New: Not primary # There is a primary key that isn't new. (There can be only one primary key) $p = Schema::getTable($this->getTable())->getPrimary(); if ($a->getPrimary() && !$n->getPrimary() || $n->getPrimary() && $p != null && !$p->equals($n)) { $primary = $p !== null ? $p : $n; foreach (Schema::getAllForeignKeyToColumn($this->getTable(), $this->schema->getName()) as $k) { $dropped_foreign[] = $k; $this->query(DB::SQL()::DROP_FOREIGN_KEY($k->getTable(), $k->getConstraint())); } $this->query($this->SQL_editColumnBasics($this->getTable(), $primary)); $this->query(DB::SQL()::DROP_PRIMARY_KEY($this->getTable())); Schema::getTable($this->getTable())->dropPrimary(); } # Update foreign column if (!$n->equalsForeign($a) && $a->getForeign()) { $this->query(DB::SQL()::DROP_FOREIGN_KEY($this->getTable(), $a->getConstraint())); # Update Schema actual $a->setConstraint(null); $a->setForeign(null, null); $a->setForeignDelete(null); $a->setForeignUpdate(null); } if ($n->getForeign()) { $this->query(DB::SQL()::DISABLE_CHECKS_FOREIGN()); $this->query($this->SQL_addForeign($this->getTable(), $this->schema)); $this->query(DB::SQL()::ENABLE_CHECKS_FOREIGN()); # Get new name of constraint $constraint = DB::first(DB::SQL()::SELECT_CONSTRAINT(DB::getName(), $this->getTable(), $a->getName()))['CONSTRAINT_NAME']; # Update Schema actual $a->setConstraint($constraint); $a->setForeign($this->schema->getForeignTable(), $this->schema->getForeignColumn()); $a->setForeignDelete($this->schema->getForeignDelete()); $a->setForeignUpdate($this->schema->getForeignUpdate()); } # Update index column if ($a->hasIndex() && !$n->hasIndex()) { $this->query(DB::SQL()::DROP_INDEX_KEY($this->getTable(), $a->getIndex())); # Update Schema actual $a->setIndex(null); } if (!$a->hasIndex() && $n->hasIndex()) { $this->query(DB::SQL()::ADD_INDEX_KEY($this->getTable(), $this->schema->getName())); # Update Schema actual $a->setIndex($a->getName()); } } foreach ($dropped_foreign as $k) { $this->query($this->SQL_addColumnForeign($k->getTable(), $k->schema)); } if (!$n->equals($a)) { # Update column # Remove tem $this->query(DB::SQL()::DISABLE_CHECKS_FOREIGN()); $this->query(DB::SQL()::EDIT_COLUMN($this->getTable(), $this->schema->getName(), $this->SQL_column($this->schema))); $this->query(DB::SQL()::ENABLE_CHECKS_FOREIGN()); # Update Schema actual Schema::getTable($this->getTable())->setColumn(clone $n); } }