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;
}