PMA\libraries\Table::moveCopy PHP Method

moveCopy() public static method

Copies or renames table
public static moveCopy ( string $source_db, string $source_table, string $target_db, string $target_table, string $what, boolean $move, string $mode ) : boolean
$source_db string source database
$source_table string source table
$target_db string target database
$target_table string target table
$what string what to be moved or copied (data, dataonly)
$move boolean whether to move
$mode string mode
return boolean true if success, false otherwise
    public static function moveCopy($source_db, $source_table, $target_db, $target_table, $what, $move, $mode)
    {
        global $err_url;
        // Try moving the tables directly, using native `RENAME` statement.
        if ($move && $what == 'data') {
            $tbl = new Table($source_table, $source_db);
            if ($tbl->rename($target_table, $target_db)) {
                $GLOBALS['message'] = $tbl->getLastMessage();
                return true;
            }
        }
        // Setting required export settings.
        $GLOBALS['sql_backquotes'] = 1;
        $GLOBALS['asfile'] = 1;
        // Ensuring the target database is valid.
        if (!$GLOBALS['dblist']->databases->exists($source_db, $target_db)) {
            if (!$GLOBALS['dblist']->databases->exists($source_db)) {
                $GLOBALS['message'] = Message::rawError(sprintf(__('Source database `%s` was not found!'), htmlspecialchars($source_db)));
            }
            if (!$GLOBALS['dblist']->databases->exists($target_db)) {
                $GLOBALS['message'] = Message::rawError(sprintf(__('Target database `%s` was not found!'), htmlspecialchars($target_db)));
            }
            return false;
        }
        /**
         * The full name of source table, quoted.
         * @var string $source
         */
        $source = Util::backquote($source_db) . '.' . Util::backquote($source_table);
        // If the target database is not specified, the operation is taking
        // place in the same database.
        if (!isset($target_db) || strlen($target_db) === 0) {
            $target_db = $source_db;
        }
        // Selecting the database could avoid some problems with replicated
        // databases, when moving table from replicated one to not replicated one.
        $GLOBALS['dbi']->selectDb($target_db);
        /**
         * The full name of target table, quoted.
         * @var string $target
         */
        $target = Util::backquote($target_db) . '.' . Util::backquote($target_table);
        // No table is created when this is a data-only operation.
        if ($what != 'dataonly') {
            include_once "libraries/plugin_interface.lib.php";
            /**
             * Instance used for exporting the current structure of the table.
             *
             * @var \PMA\libraries\plugins\export\ExportSql
             */
            $export_sql_plugin = PMA_getPlugin("export", "sql", 'libraries/plugins/export/', array('export_type' => 'table', 'single_table' => false));
            $no_constraints_comments = true;
            $GLOBALS['sql_constraints_query'] = '';
            // set the value of global sql_auto_increment variable
            if (isset($_POST['sql_auto_increment'])) {
                $GLOBALS['sql_auto_increment'] = $_POST['sql_auto_increment'];
            }
            /**
             * The old structure of the table..
             * @var string $sql_structure
             */
            $sql_structure = $export_sql_plugin->getTableDef($source_db, $source_table, "\n", $err_url, false, false);
            unset($no_constraints_comments);
            // -----------------------------------------------------------------
            // Phase 0: Preparing structures used.
            /**
             * The destination where the table is moved or copied to.
             * @var Expression
             */
            $destination = new Expression($target_db, $target_table, '');
            // Find server's SQL mode so the builder can generate correct
            // queries.
            // One of the options that alters the behaviour is `ANSI_QUOTES`.
            Context::setMode($GLOBALS['dbi']->fetchValue("SELECT @@sql_mode"));
            // -----------------------------------------------------------------
            // Phase 1: Dropping existent element of the same name (if exists
            // and required).
            if (isset($_REQUEST['drop_if_exists']) && $_REQUEST['drop_if_exists'] == 'true') {
                /**
                 * Drop statement used for building the query.
                 * @var DropStatement $statement
                 */
                $statement = new DropStatement();
                $tbl = new Table($target_db, $target_table);
                $statement->options = new OptionsArray(array($tbl->isView() ? 'VIEW' : 'TABLE', 'IF EXISTS'));
                $statement->fields = array($destination);
                // Building the query.
                $drop_query = $statement->build() . ';';
                // Executing it.
                $GLOBALS['dbi']->query($drop_query);
                $GLOBALS['sql_query'] .= "\n" . $drop_query;
                // If an existing table gets deleted, maintain any entries for
                // the PMA_* tables.
                $maintain_relations = true;
            }
            // -----------------------------------------------------------------
            // Phase 2: Generating the new query of this structure.
            /**
             * The parser responsible for parsing the old queries.
             * @var Parser $parser
             */
            $parser = new Parser($sql_structure);
            if (!empty($parser->statements[0])) {
                /**
                 * The CREATE statement of this structure.
                 * @var \SqlParser\Statements\CreateStatement $statement
                 */
                $statement = $parser->statements[0];
                // Changing the destination.
                $statement->name = $destination;
                // Building back the query.
                $sql_structure = $statement->build() . ';';
                // Executing it.
                $GLOBALS['dbi']->query($sql_structure);
                $GLOBALS['sql_query'] .= "\n" . $sql_structure;
            }
            // -----------------------------------------------------------------
            // Phase 3: Adding constraints.
            // All constraint names are removed because they must be unique.
            if (($move || isset($GLOBALS['add_constraints'])) && !empty($GLOBALS['sql_constraints_query'])) {
                $parser = new Parser($GLOBALS['sql_constraints_query']);
                /**
                 * The ALTER statement that generates the constraints.
                 * @var \SqlParser\Statements\AlterStatement $statement
                 */
                $statement = $parser->statements[0];
                // Changing the altered table to the destination.
                $statement->table = $destination;
                // Removing the name of the constraints.
                foreach ($statement->altered as $idx => $altered) {
                    // All constraint names are removed because they must be unique.
                    if ($altered->options->has('CONSTRAINT')) {
                        $altered->field = null;
                    }
                }
                // Building back the query.
                $GLOBALS['sql_constraints_query'] = $statement->build() . ';';
                // Executing it.
                if ($mode == 'one_table') {
                    $GLOBALS['dbi']->query($GLOBALS['sql_constraints_query']);
                }
                $GLOBALS['sql_query'] .= "\n" . $GLOBALS['sql_constraints_query'];
                if ($mode == 'one_table') {
                    unset($GLOBALS['sql_constraints_query']);
                }
            }
            // -----------------------------------------------------------------
            // Phase 4: Adding indexes.
            // View phase 3.
            if (!empty($GLOBALS['sql_indexes'])) {
                $parser = new Parser($GLOBALS['sql_indexes']);
                $GLOBALS['sql_indexes'] = '';
                /**
                 * The ALTER statement that generates the indexes.
                 * @var \SqlParser\Statements\AlterStatement $statement
                 */
                foreach ($parser->statements as $statement) {
                    // Changing the altered table to the destination.
                    $statement->table = $destination;
                    // Removing the name of the constraints.
                    foreach ($statement->altered as $idx => $altered) {
                        // All constraint names are removed because they must be unique.
                        if ($altered->options->has('CONSTRAINT')) {
                            $altered->field = null;
                        }
                    }
                    // Building back the query.
                    $sql_index = $statement->build() . ';';
                    // Executing it.
                    if ($mode == 'one_table' || $mode == 'db_copy') {
                        $GLOBALS['dbi']->query($sql_index);
                    }
                    $GLOBALS['sql_indexes'] .= $sql_index;
                }
                $GLOBALS['sql_query'] .= "\n" . $GLOBALS['sql_indexes'];
                if ($mode == 'one_table' || $mode == 'db_copy') {
                    unset($GLOBALS['sql_indexes']);
                }
            }
            // -----------------------------------------------------------------
            // Phase 5: Adding AUTO_INCREMENT.
            if (!empty($GLOBALS['sql_auto_increments'])) {
                if ($mode == 'one_table' || $mode == 'db_copy') {
                    $parser = new Parser($GLOBALS['sql_auto_increments']);
                    /**
                     * The ALTER statement that alters the AUTO_INCREMENT value.
                     * @var \SqlParser\Statements\AlterStatement $statement
                     */
                    $statement = $parser->statements[0];
                    // Changing the altered table to the destination.
                    $statement->table = $destination;
                    // Building back the query.
                    $GLOBALS['sql_auto_increments'] = $statement->build() . ';';
                    // Executing it.
                    $GLOBALS['dbi']->query($GLOBALS['sql_auto_increments']);
                    $GLOBALS['sql_query'] .= "\n" . $GLOBALS['sql_auto_increments'];
                    unset($GLOBALS['sql_auto_increments']);
                }
            }
        } else {
            $GLOBALS['sql_query'] = '';
        }
        $_table = new Table($target_table, $target_db);
        // Copy the data unless this is a VIEW
        if (($what == 'data' || $what == 'dataonly') && !$_table->isView()) {
            $sql_set_mode = "SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO'";
            $GLOBALS['dbi']->query($sql_set_mode);
            $GLOBALS['sql_query'] .= "\n\n" . $sql_set_mode . ';';
            $_old_table = new Table($source_table, $source_db);
            $nonGeneratedCols = $_old_table->getNonGeneratedColumns(true);
            if (count($nonGeneratedCols) > 0) {
                $sql_insert_data = 'INSERT INTO ' . $target . '(' . implode(', ', $nonGeneratedCols) . ') SELECT ' . implode(', ', $nonGeneratedCols) . ' FROM ' . $source;
                $GLOBALS['dbi']->query($sql_insert_data);
                $GLOBALS['sql_query'] .= "\n\n" . $sql_insert_data . ';';
            }
        }
        PMA_getRelationsParam();
        // Drops old table if the user has requested to move it
        if ($move) {
            // This could avoid some problems with replicated databases, when
            // moving table from replicated one to not replicated one
            $GLOBALS['dbi']->selectDb($source_db);
            $_source_table = new Table($source_table, $source_db);
            if ($_source_table->isView()) {
                $sql_drop_query = 'DROP VIEW';
            } else {
                $sql_drop_query = 'DROP TABLE';
            }
            $sql_drop_query .= ' ' . $source;
            $GLOBALS['dbi']->query($sql_drop_query);
            // Renable table in configuration storage
            PMA_REL_renameTable($source_db, $target_db, $source_table, $target_table);
            $GLOBALS['sql_query'] .= "\n\n" . $sql_drop_query . ';';
            // end if ($move)
            return true;
        }
        // we are copying
        // Create new entries as duplicates from old PMA DBs
        if ($what == 'dataonly' || isset($maintain_relations)) {
            return true;
        }
        if ($GLOBALS['cfgRelation']['commwork']) {
            // Get all comments and MIME-Types for current table
            $comments_copy_rs = PMA_queryAsControlUser('SELECT column_name, comment' . ($GLOBALS['cfgRelation']['mimework'] ? ', mimetype, transformation, transformation_options' : '') . ' FROM ' . Util::backquote($GLOBALS['cfgRelation']['db']) . '.' . Util::backquote($GLOBALS['cfgRelation']['column_info']) . ' WHERE ' . ' db_name = \'' . $GLOBALS['dbi']->escapeString($source_db) . '\'' . ' AND ' . ' table_name = \'' . $GLOBALS['dbi']->escapeString($source_table) . '\'');
            // Write every comment as new copied entry. [MIME]
            while ($comments_copy_row = $GLOBALS['dbi']->fetchAssoc($comments_copy_rs)) {
                $new_comment_query = 'REPLACE INTO ' . Util::backquote($GLOBALS['cfgRelation']['db']) . '.' . Util::backquote($GLOBALS['cfgRelation']['column_info']) . ' (db_name, table_name, column_name, comment' . ($GLOBALS['cfgRelation']['mimework'] ? ', mimetype, transformation, transformation_options' : '') . ') ' . ' VALUES(' . '\'' . $GLOBALS['dbi']->escapeString($target_db) . '\',\'' . $GLOBALS['dbi']->escapeString($target_table) . '\',\'' . $GLOBALS['dbi']->escapeString($comments_copy_row['column_name']) . '\'' . ($GLOBALS['cfgRelation']['mimework'] ? ',\'' . $GLOBALS['dbi']->escapeString($comments_copy_row['comment']) . '\',' . '\'' . $GLOBALS['dbi']->escapeString($comments_copy_row['mimetype']) . '\',' . '\'' . $GLOBALS['dbi']->escapeString($comments_copy_row['transformation']) . '\',' . '\'' . $GLOBALS['dbi']->escapeString($comments_copy_row['transformation_options']) . '\'' : '') . ')';
                PMA_queryAsControlUser($new_comment_query);
            }
            // end while
            $GLOBALS['dbi']->freeResult($comments_copy_rs);
            unset($comments_copy_rs);
        }
        // duplicating the bookmarks must not be done here, but
        // just once per db
        $get_fields = array('display_field');
        $where_fields = array('db_name' => $source_db, 'table_name' => $source_table);
        $new_fields = array('db_name' => $target_db, 'table_name' => $target_table);
        Table::duplicateInfo('displaywork', 'table_info', $get_fields, $where_fields, $new_fields);
        /**
         * @todo revise this code when we support cross-db relations
         */
        $get_fields = array('master_field', 'foreign_table', 'foreign_field');
        $where_fields = array('master_db' => $source_db, 'master_table' => $source_table);
        $new_fields = array('master_db' => $target_db, 'foreign_db' => $target_db, 'master_table' => $target_table);
        Table::duplicateInfo('relwork', 'relation', $get_fields, $where_fields, $new_fields);
        $get_fields = array('foreign_field', 'master_table', 'master_field');
        $where_fields = array('foreign_db' => $source_db, 'foreign_table' => $source_table);
        $new_fields = array('master_db' => $target_db, 'foreign_db' => $target_db, 'foreign_table' => $target_table);
        Table::duplicateInfo('relwork', 'relation', $get_fields, $where_fields, $new_fields);
        /**
        * @todo Can't get duplicating PDFs the right way. The
        * page numbers always get screwed up independently from
        * duplication because the numbers do not seem to be stored on a
        * per-database basis. Would the author of pdf support please
        * have a look at it?
        *
                $get_fields = array('page_descr');
                $where_fields = array('db_name' => $source_db);
                $new_fields = array('db_name' => $target_db);
                $last_id = Table::duplicateInfo(
           'pdfwork',
           'pdf_pages',
           $get_fields,
           $where_fields,
           $new_fields
                );
        
                if (isset($last_id) && $last_id >= 0) {
           $get_fields = array('x', 'y');
           $where_fields = array(
               'db_name' => $source_db,
               'table_name' => $source_table
           );
           $new_fields = array(
               'db_name' => $target_db,
               'table_name' => $target_table,
               'pdf_page_number' => $last_id
           );
           Table::duplicateInfo(
               'pdfwork',
               'table_coords',
               $get_fields,
               $where_fields,
               $new_fields
           );
                }
        */
        return true;
    }

Usage Example

Example #1
0
 /**
  * Test for moveCopy
  *
  * @return void
  */
 public function testMoveCopy()
 {
     $source_table = 'PMA_BookMark';
     $source_db = 'PMA';
     $target_table = 'PMA_BookMark_new';
     $target_db = 'PMA_new';
     $what = "dataonly";
     $move = true;
     $mode = "one_table";
     $GLOBALS['dbi']->expects($this->any())->method('getTable')->will($this->returnValue(new Table($target_table, $target_db)));
     $_REQUEST['drop_if_exists'] = true;
     $return = Table::moveCopy($source_db, $source_table, $target_db, $target_table, $what, $move, $mode);
     //successfully
     $expect = true;
     $this->assertEquals($expect, $return);
     $sql_query = "INSERT INTO `PMA_new`.`PMA_BookMark_new` SELECT * FROM " . "`PMA`.`PMA_BookMark`";
     $this->assertContains($sql_query, $GLOBALS['sql_query']);
     $sql_query = "DROP VIEW `PMA`.`PMA_BookMark`";
     $this->assertContains($sql_query, $GLOBALS['sql_query']);
     $return = Table::moveCopy($source_db, $source_table, $target_db, $target_table, $what, false, $mode);
     //successfully
     $expect = true;
     $this->assertEquals($expect, $return);
     $sql_query = "INSERT INTO `PMA_new`.`PMA_BookMark_new` SELECT * FROM " . "`PMA`.`PMA_BookMark`;";
     $this->assertContains($sql_query, $GLOBALS['sql_query']);
     $sql_query = "DROP VIEW `PMA`.`PMA_BookMark`";
     $this->assertNotContains($sql_query, $GLOBALS['sql_query']);
 }
All Usage Examples Of PMA\libraries\Table::moveCopy