public function execute($direction, $replay = false)
    {
        if ('down' === $direction && $replay) {
            throw new AbortException(
                'Cannot run \'down\' and replay it. Use replay with \'up\''
            );
        }

        try {
            $start = microtime(true);

            $this->state = self::STATE_PRE;

            $this->migration->{'pre' . ucfirst($direction)}($this->db);

            if ('up' === $direction) {
                $this->outputWriter->write("\n" . sprintf('  <info>++</info> migrating <comment>%s</comment>', $this->version) . "\n");
            } else {
                $this->outputWriter->write("\n" . sprintf('  <info>--</info> reverting <comment>%s</comment>', $this->version) . "\n");
            }

            $this->state = self::STATE_EXEC;

            $this->migration->$direction($this->db);

            $this->updateStatisticsAfter();

            if ('up' === $direction) {
                $this->markMigrated($replay);
            } else {
                $this->markNotMigrated();
            }

            $this->summarizeStatistics();

            $this->state = self::STATE_POST;
            $this->migration->{'post' . ucfirst($direction)}($this->db);

            $end = microtime(true);
            $this->time = round($end - $start, 2);
            if ('up' === $direction) {
                $this->outputWriter->write(sprintf("\n  <info>++</info> migrated (%ss)", $this->time));
            } else {
                $this->outputWriter->write(sprintf("\n  <info>--</info> reverted (%ss)", $this->time));
            }

            $this->state = self::STATE_NONE;
        } catch (SkipException $e) {
            // now mark it as migrated
            if ('up' === $direction) {
                $this->markMigrated();
            } else {
                $this->markNotMigrated();
            }

            $this->outputWriter->write(sprintf("\n  <info>SS</info> skipped (Reason: %s)", $e->getMessage()));

            $this->state = self::STATE_NONE;
        } catch (\Exception $e) {
            $this->outputWriter->write(sprintf(
                '<error>Migration %s failed during %s. Error %s</error>',
                $this->version, $this->getExecutionState(), $e->getMessage()
            ));

            $this->state = self::STATE_NONE;
            throw $e;
        }
    }