phpmyadmin/tbl_relation.php
Jason cb771052c8 Finish refactoring tbl_*.lib.php
Signed-off-by: Jason <jason.daurus@gmail.com>
2015-06-17 01:14:27 +08:00

266 lines
9.0 KiB
PHP

<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* Display table relations for viewing and editing
*
* includes phpMyAdmin relations and InnoDB relations
*
* @todo fix name handling: currently names with dots (.) are not properly handled
* for internal relations (but foreign keys relations are correct)
* @todo foreign key constraints require both fields being of equal type and size
* @todo check foreign fields to be from same type and size, all other makes no sense
* @todo if above todos are fullfilled we can add all fields meet requirements
* in the select dropdown
* @package PhpMyAdmin
*/
/**
* Gets some core libraries
*/
require_once 'libraries/common.inc.php';
require_once 'libraries/index.lib.php';
require_once 'libraries/Template.class.php';
require_once 'libraries/Table.class.php';
require_once 'libraries/structure.lib.php';
$response = PMA_Response::getInstance();
// Send table of column names to populate corresponding dropdowns depending
// on the current selection
if (isset($_REQUEST['getDropdownValues'])
&& $_REQUEST['getDropdownValues'] === 'true'
) {
if (isset($_REQUEST['foreignTable'])) { // if both db and table are selected
$foreignTable = $_REQUEST['foreignTable'];
$table_obj = new PMA_Table($foreignTable, $_REQUEST['foreignDb']);
// Since views do not have keys defined on them provide the full list of columns
if (PMA_Table::isView($_REQUEST['foreignDb'], $foreignTable)) {
$columnList = $table_obj->getColumns(false, false);
} else {
$columnList = $table_obj->getIndexedColumns(false, false);
}
$columns = array();
foreach ($columnList as $column) {
$columns[] = htmlspecialchars($column);
}
$response->addJSON('columns', $columns);
// @todo should be: $server->db($db)->table($table)->primary()
$primary = PMA_Index::getPrimary($foreignTable, $_REQUEST['foreignDb']);
if (false === $primary) {
return;
}
$primarycols = array_keys($primary->getColumns());
$response->addJSON('primary', $primarycols);
} else { // if only the db is selected
$tables = array();
$foreign = isset($_REQUEST['foreign']) && $_REQUEST['foreign'] === 'true';
if ($foreign) {
$tbl_storage_engine = /*overload*/mb_strtoupper(
PMA_Table::sGetStatusInfo(
$_REQUEST['db'],
$_REQUEST['table'],
'Engine'
)
);
}
// In Drizzle, 'SHOW TABLE STATUS' will show status only for the tables
// which are currently in the table cache. Hence we have to use 'SHOW TABLES'
// and manually retrieve table engine values.
if ($foreign && ! PMA_DRIZZLE) {
$query = 'SHOW TABLE STATUS FROM '
. PMA_Util::backquote($_REQUEST['foreignDb']);
$tables_rs = $GLOBALS['dbi']->query(
$query,
null,
PMA_DatabaseInterface::QUERY_STORE
);
while ($row = $GLOBALS['dbi']->fetchArray($tables_rs)) {
if (isset($row['Engine'])
&& /*overload*/mb_strtoupper($row['Engine']) == $tbl_storage_engine
) {
$tables[] = htmlspecialchars($row['Name']);
}
}
} else {
$query = 'SHOW TABLES FROM '
. PMA_Util::backquote($_REQUEST['foreignDb']);
$tables_rs = $GLOBALS['dbi']->query(
$query,
null,
PMA_DatabaseInterface::QUERY_STORE
);
while ($row = $GLOBALS['dbi']->fetchArray($tables_rs)) {
if ($foreign && PMA_DRIZZLE) {
$engine = /*overload*/mb_strtoupper(
PMA_Table::sGetStatusInfo(
$_REQUEST['foreignDb'],
$row[0],
'Engine'
)
);
if (isset($engine) && $engine == $tbl_storage_engine) {
$tables[] = htmlspecialchars($row[0]);
}
} else {
$tables[] = htmlspecialchars($row[0]);
}
}
}
$response->addJSON('tables', $tables);
}
exit;
}
$header = $response->getHeader();
$scripts = $header->getScripts();
$scripts->addFile('tbl_relation.js');
$scripts->addFile('indexes.js');
/**
* Gets tables information
*/
require_once 'libraries/tbl_info.inc.php';
$options_array = array(
'CASCADE' => 'CASCADE',
'SET_NULL' => 'SET NULL',
'NO_ACTION' => 'NO ACTION',
'RESTRICT' => 'RESTRICT',
);
/**
* Gets the relation settings
*/
$cfgRelation = PMA_getRelationsParam();
/**
* Updates
*/
if ($cfgRelation['relwork']) {
$existrel = PMA_getForeigners($db, $table, '', 'internal');
}
if (PMA_Util::isForeignKeySupported($tbl_storage_engine)) {
$existrel_foreign = PMA_getForeigners($db, $table, '', 'foreign');
}
if ($cfgRelation['displaywork']) {
$disp = PMA_getDisplayField($db, $table);
} else {
$disp = '';
}
// will be used in the logic for internal relations and foreign keys:
$multi_edit_columns_name = isset($_REQUEST['fields_name'])
? $_REQUEST['fields_name']
: null;
$html_output = '';
$upd_query = new PMA_Table($table, $db, $GLOBALS['dbi']);
// u p d a t e s f o r I n t e r n a l r e l a t i o n s
if (isset($_POST['destination_db']) && $cfgRelation['relwork']) {
if ($upd_query->updateInternalRelations(
$multi_edit_columns_name, $_POST['destination_db'], $_POST['destination_table'],
$_POST['destination_column'], $cfgRelation, isset($existrel) ? $existrel : null
)) {
$html_output .= PMA_Util::getMessage(
__('Internal relations were successfully updated.'),
'', 'success'
);
}
} // end if (updates for internal relations)
$multi_edit_columns_name = isset($_REQUEST['foreign_key_fields_name'])
? $_REQUEST['foreign_key_fields_name']
: null;
// u p d a t e s f o r f o r e i g n k e y s
// (for now, one index name only; we keep the definitions if the
// foreign db is not the same)
if (isset($_POST['destination_foreign_db'])) {
list($html, $preview_sql_data, $display_query, $seen_error) = $upd_query->updateForeignKeys(
$_POST['destination_foreign_db'],
$multi_edit_columns_name, $_POST['destination_foreign_table'],
$_POST['destination_foreign_column'], $options_array, $table,
isset($existrel_foreign) ? $existrel_foreign['foreign_keys_data'] : null
);
$html_output .= $html;
// If there is a request for SQL previewing.
if (isset($_REQUEST['preview_sql'])) {
PMA_previewSQL($preview_sql_data);
}
if (! empty($display_query) && ! $seen_error) {
$GLOBALS['display_query'] = $display_query;
$html_output .= PMA_Util::getMessage(
__('Your SQL query has been executed successfully.'),
null, 'success'
);
}
} // end if isset($destination_foreign)
// U p d a t e s f o r d i s p l a y f i e l d
if ($cfgRelation['displaywork'] && isset($_POST['display_field'])) {
if ($upd_query->updateDisplayField($disp, $_POST['display_field'], $cfgRelation)) {
$html_output .= PMA_Util::getMessage(
__('Display column was successfully updated.'),
'', 'success'
);
}
} // end if
// If we did an update, refresh our data
if (isset($_POST['destination_db']) && $cfgRelation['relwork']) {
$existrel = PMA_getForeigners($db, $table, '', 'internal');
}
if (isset($_POST['destination_foreign_db'])
&& PMA_Util::isForeignKeySupported($tbl_storage_engine)
) {
$existrel_foreign = PMA_getForeigners($db, $table, '', 'foreign');
}
if ($cfgRelation['displaywork']) {
$disp = PMA_getDisplayField($db, $table);
}
// display secondary level tabs if necessary
$engine = PMA_Table::sGetStatusInfo($db, $table, 'ENGINE');
$response->addHTML(PMA_getStructureSecondaryTabs($engine));
$response->addHTML('<div id="structure_content">');
/**
* Dialog
*/
// Now find out the columns of our $table
// need to use PMA_DatabaseInterface::QUERY_STORE with $GLOBALS['dbi']->numRows()
// in mysqli
$columns = $GLOBALS['dbi']->getColumns($db, $table);
// common form
$html_output .= PMA\Template::get('tbl_relation/common_form')->render(
array(
'db' => $db,
'table' => $table,
'columns' => $columns,
'cfgRelation' => $cfgRelation,
'tbl_storage_engine' => $tbl_storage_engine,
'existrel' => isset($existrel) ? $existrel : array(),
'existrel_foreign' => isset($existrel_foreign) ? $existrel_foreign['foreign_keys_data'] : array(),
'options_array' => $options_array
)
);
if (PMA_Util::isForeignKeySupported($tbl_storage_engine)) {
$html_output .= PMA_getHtmlForDisplayIndexes();
}
// Render HTML output
$response->addHTML($html_output);
$response->addHTML('</div>');