db = $db; } /** * @param string $indexName * * @throws EscapingException * * @return string */ private function generateName(string $indexName): string { if (!empty($indexName)) { $indexName = $this->escape($indexName); } return $indexName; } /** * @param $creatorIndex * * @throws EscapingException * * @return string */ private function buildReferences($creatorIndex): string { if ($creatorIndex instanceof Constraint) { $default = ['delete']; $asCascade = $creatorIndex->getCascadeOn(); if (empty($asCascade)) { $asCascade = $default; } $cascade = ''; foreach ($asCascade as $cascadeCase) { $cascade .= sprintf(' ON %s CASCADE ', strtoupper($cascadeCase)); } return sprintf( 'FOREIGN KEY (%s) REFERENCES %s (%s)%s', implode(',', array_map([$this, 'escape'],$creatorIndex->getForeignKey())), $this->escape($creatorIndex->getParentTable()), implode(',', array_map([$this, 'escape'], $creatorIndex->getParenId())), $cascade ); } $reference = implode( ',', array_map( function ($reference) { return $this->escape($reference); }, $creatorIndex->getReferences() ) ); return sprintf('(%s)', $reference); } /** * @param IndexInterface $creatorIndex * * @throws EscapingException * * @return string */ public function generateLine(IndexInterface $creatorIndex): string { $line = $creatorIndex->getType(); if (!($creatorIndex instanceof PrimaryKeyInterface)) { $lineName = $this->generateName($creatorIndex->getName()); $line .= ' ' . $lineName; } $line .= ' ' . $this->buildReferences($creatorIndex); return trim($line); } /** * @param IndexInterface $creatorIndex * * @return string */ private function getName(IndexInterface $creatorIndex): string { return $creatorIndex->getName() ?? ''; } /** * @param IndexInterface $creatorIndex * * @return string */ public function getKeyName(IndexInterface $creatorIndex): string { if ($creatorIndex instanceof PrimaryKeyInterface) { return 'PRIMARY'; } $keyName = $this->getName($creatorIndex); return $keyName ?? trim(str_replace('KEY', '', $creatorIndex->getType())); } /** * @param string $tableName * * @throws LineGeneratorException * * @return array */ public function fetchIndexesFromDb(string $tableName): array { try { $indexes = $this->db->fetchAll('SHOW INDEXES FROM ' . $this->db->escapeIdentifier($tableName)); } catch (QueryFailureException | EscapingException $exception) { throw new LineGeneratorException( $exception->getMessage(), $exception->getCode(), $exception->getPrevious() ); } $result = []; foreach ($indexes as $index) { $keyName = $index['Key_name']; $resultKey = array_search($keyName, array_column($result, 'name'), true); if ($resultKey !== false) { $result[$resultKey]['columns'][] = $index['Column_name']; } if ($resultKey === false) { $result[] = [ 'name' => $index['Key_name'], 'columns' => [$index['Column_name']], 'unique' => (int)$index['Non_unique'] === 0, ]; } } return $result; } /** * @param string $name * * @throws EscapingException * * @return string */ public function escape(string $name): string { return $this->db->escapeIdentifier($name); } }