db->tableExists('invoice_students_list') || ! $this->db->fieldExists('semester', 'invoice_students_list')) { return; } foreach ($this->indexesContainingColumn('invoice_students_list', 'semester') as $indexName) { $this->dropIndexIfExists('invoice_students_list', $indexName); } $this->forge->dropColumn('invoice_students_list', 'semester'); $this->db->resetDataCache(); } public function down(): void { if (! $this->db->tableExists('invoice_students_list') || $this->db->fieldExists('semester', 'invoice_students_list')) { return; } $this->forge->addColumn('invoice_students_list', [ 'semester' => [ 'type' => 'VARCHAR', 'constraint' => 10, 'null' => true, 'after' => 'school_year', ], ]); $this->db->resetDataCache(); } /** * @return list */ private function indexesContainingColumn(string $table, string $column): array { $rows = $this->db->query( 'SELECT DISTINCT INDEX_NAME FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ? AND INDEX_NAME <> \'PRIMARY\'', [$table, $column] )->getResultArray(); return array_values(array_filter(array_map( static fn (array $row): string => (string) ($row['INDEX_NAME'] ?? ''), $rows ))); } private function dropIndexIfExists(string $table, string $index): void { if ($index === '') { return; } $exists = $this->db->query( 'SELECT COUNT(*) AS aggregate FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND INDEX_NAME = ?', [$table, $index] )->getRow(); if ((int) ($exists->aggregate ?? 0) === 0) { return; } $this->db->query(sprintf( 'ALTER TABLE %s DROP INDEX %s', $this->db->escapeIdentifiers($table), $this->db->escapeIdentifiers($index) )); } }