public function schemaUpdate($callback)
    {
        // Begin schema update
        $this->schemaIsUpdating = true;

        // Update table list
        $this->tableList = array();
        $tables = $this->tableList();
        foreach ($tables as $table) {
            $this->tableList[strtolower($table)] = $table;
        }

        // Clear update list for client code to mess around with
        $this->schemaUpdateTransaction = array();

        /** @var Exception $error */
        $error = null;
        try {
            // Yield control to client code
            $callback();

            // If the client code has cancelled the update then abort
            if (!$this->isSchemaUpdating()) {
                return;
            }

            // End schema update
            foreach ($this->schemaUpdateTransaction as $tableName => $changes) {
                $advancedOptions = isset($changes['advancedOptions']) ? $changes['advancedOptions'] : null;
                switch ($changes['command']) {
                    case 'create':
                        $this->createTable(
                            $tableName,
                            $changes['newFields'],
                            $changes['newIndexes'],
                            $changes['options'],
                            $advancedOptions
                        );
                        break;

                    case 'alter':
                        $this->alterTable(
                            $tableName,
                            $changes['newFields'],
                            $changes['newIndexes'],
                            $changes['alteredFields'],
                            $changes['alteredIndexes'],
                            $changes['alteredOptions'],
                            $advancedOptions
                        );
                        break;
                }
            }
        } finally {
            $this->schemaUpdateTransaction = null;
            $this->schemaIsUpdating = false;
        }
    }