public function loadColumn(Column $column) { if ($column->isSynced()) { return $this; } $name = $this->quoteName($column->getDatabase(), $column->getTable()); $stmt = $this->query("SHOW COLUMNS IN {$name} WHERE `Field`=?", [$column->getName()]); $info = $stmt->fetchObject(); $matches = []; if (!preg_match('/^(?<type>[a-zA-Z]+)(?:\\((?<extra>[^\\)]+)\\))?$/i', $info->Type, $matches)) { throw new Exception("Received unexpected type {$info->Type} from database, failed to parse it."); } $type = $this->mapColumnType(strtolower($matches['type']), true); $extra = isset($matches['extra']) ? $matches['extra'] : null; if ($extra) { if (is_numeric($extra)) { $maxLength = intval($extra); if ($type === 'bool' && $maxLength > 1) { $type = 'byte'; } $column->setMaxLength($maxLength); } else { $column->setAllowedValues(array_map(function ($val) { return trim($val, '"\''); }, explode(',', $extra))); } } $column->setType($type); switch (strtolower($info->Null)) { case 'no': $column->makeRequired(); break; default: case 'yes': $column->makeOptional(); break; } switch (strtolower($info->Key)) { case 'pri': $column->makePrimary(); break; case 'uni': $column->makeUnique(); break; case 'mul': $table = $column->getTable(); $fkName = "{$table}_{$column}_FK"; $stmt = $this->query('SELECT `REFERENCED_TABLE_SCHEMA` AS `db`, ' . '`REFERENCED_TABLE_NAME` AS `tbl`, ' . '`REFERENCED_COLUMN_NAME` AS `col` ' . 'FROM `information_schema`.`KEY_COLUMN_USAGE` ' . 'WHERE `CONSTRAINT_SCHEMA`=? AND `CONSTRAINT_NAME`=?', [$column->getDatabase()->getName(), $fkName]); $refInfo = $stmt->fetchObject(); if ($refInfo) { $refCol = $column->getSource()->getDatabase($refInfo->db)->getTable($refInfo->tbl)->getColumn($refInfo->col); $column->reference($refCol); } else { $column->makeIndex(); } break; } if (!empty($info->Default)) { $column->setDefaultValue($info->Default); } if ($info->Extra == 'auto_increment') { $column->autoIncrease(); } return $this; }