prefix . TableNames::REPORT_LINKS; if ( ! $this->column_exists( $wpdb, $table ) ) { return true; } if ( $this->index_exists( $wpdb, $table ) ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.SchemaChange -- One-off schema change. $wpdb->query( $wpdb->prepare( 'ALTER TABLE %i DROP INDEX %i', $table, self::COLUMN ) ); } // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.SchemaChange -- One-off schema change. $wpdb->query( $wpdb->prepare( 'ALTER TABLE %i DROP COLUMN %i', $table, self::COLUMN ) ); // Verified rather than assumed, so a failed ALTER leaves the schema // version where it was and the migration retries. return ! $this->column_exists( $wpdb, $table ); } /** * Reads live schema, so its answer changes once the ALTER runs. * * @phpstan-impure * * @param \wpdb $wpdb Database handle. * @param string $table Table name. */ private function column_exists( \wpdb $wpdb, string $table ): bool { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Schema inspection. return null !== $wpdb->get_row( $wpdb->prepare( 'SHOW COLUMNS FROM %i LIKE %s', $table, self::COLUMN ) ); } /** * @param \wpdb $wpdb Database handle. * @param string $table Table name. */ private function index_exists( \wpdb $wpdb, string $table ): bool { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Schema inspection. return null !== $wpdb->get_row( $wpdb->prepare( 'SHOW INDEX FROM %i WHERE Key_name = %s', $table, self::COLUMN ) ); } }