/**
  * Convert a primary key column from one format to another.
  *
  * @param  IdProperty    $newProp  The new ID property.
  * @param  PropertyField $newField The new ID field.
  * @param  IdProperty    $oldProp  The previous ID property.
  * @param  PropertyField $oldField The previous ID field.
  * @throws InvalidArgumentException If the new property does not implement the proper mode.
  * @return self
  */
 protected function convertIdField(IdProperty $newProp, PropertyField $newField, IdProperty $oldProp, PropertyField $oldField)
 {
     $cli = $this->climate();
     $keepId = $cli->arguments->defined('keep_id');
     $model = $this->targetModel();
     $source = $model->source();
     $table = $source->table();
     $db = $source->db();
     $newKey = $newProp->ident();
     $oldKey = $oldProp->ident();
     $this->insertNewField($newField, $newProp);
     $rows = $this->fetchTargetRows();
     if ($this->describeCount($rows)) {
         if (!$this->quiet()) {
             $cli->br();
             $progress = $cli->progress($rows->rowCount());
         }
         if ($newProp->mode() === IdProperty::MODE_AUTO_INCREMENT) {
             $pool = 0;
             $ids = function () use(&$pool) {
                 return ++$pool;
             };
         } else {
             $pool = [];
             $ids = function () use(&$pool, $newProp) {
                 $id = $newProp->autoGenerate();
                 while (in_array($id, $pool)) {
                     $id = $newProp->autoGenerate();
                 }
                 $pool[] = $id;
                 return $id;
             };
         }
         foreach ($rows as $row) {
             $id = $ids();
             $sql = strtr('UPDATE `%table` SET `%newKey` = :new WHERE `%oldKey` = :old;', ['%table' => $table, '%newKey' => $newKey, '%oldKey' => $oldKey]);
             $source->dbQuery($sql, ['new' => $id, 'old' => $row[$oldKey]], ['new' => $newField->sqlPdoType(), 'old' => $oldField->sqlPdoType()]);
             if (!$this->quiet()) {
                 $progress->advance();
             }
         }
     }
     $this->dropPrimaryKey($oldField, $oldProp);
     $this->applyPrimaryKey($newField, $newProp);
     /** @todo Alter related tables */
     $this->syncRelatedFields($newProp, $newField, $oldProp, $oldField);
     if (!$keepId) {
         $this->removeColumn($oldField);
     }
     $this->renameColumn($newField, $newKey, $oldKey);
     return $this;
 }