Merge pull request #438 from kasunchathuranga/relView
Relational view interface improvements
This commit is contained in:
commit
45b0820234
11
doc/faq.rst
11
doc/faq.rst
@ -881,8 +881,7 @@ TableSeparator or disabling that feature.
|
||||
3.6 What is currently not supported in phpMyAdmin about InnoDB?
|
||||
---------------------------------------------------------------
|
||||
|
||||
In Relation view, being able to choose a table in another database, or
|
||||
having more than one index column in the foreign key. In Query-by-
|
||||
In Relation view, having more than one index column in the foreign key. In Query-by-
|
||||
example (Query), automatic generation of the query LEFT JOIN from the
|
||||
foreign table.
|
||||
|
||||
@ -1378,7 +1377,7 @@ look for the word "upload" in this document.
|
||||
---------------------------------------------------------
|
||||
|
||||
Here is an example with the tables persons, towns and countries, all
|
||||
located in the database mydb. If you don't have a ``pma__relation``
|
||||
located in the database "mydb". If you don't have a ``pma__relation``
|
||||
table, create it as explained in the configuration section. Then
|
||||
create the example tables:
|
||||
|
||||
@ -1416,8 +1415,10 @@ create the example tables:
|
||||
To setup appropriate links and display information:
|
||||
|
||||
* on table "REL\_persons" click Structure, then Relation view
|
||||
* in Links, for "town\_code" choose "REL\_towns->code"
|
||||
* in Links, for "country\_code" choose "REL\_countries->country\_code"
|
||||
* for "town\_code", choose from dropdowns, "mydb", "REL\_towns", "code"
|
||||
for foreign database, table and column respectively
|
||||
* for "country\_code", choose from dropdowns, "mydb", "REL\_countries",
|
||||
"country\_code" for foreign database, table and column respectively
|
||||
* on table "REL\_towns" click Structure, then Relation view
|
||||
* in "Choose column to display", choose "description"
|
||||
* repeat the two previous steps for table "REL\_countries"
|
||||
|
||||
@ -5,30 +5,123 @@
|
||||
*/
|
||||
function show_hide_clauses($thisDropdown)
|
||||
{
|
||||
// here, one span contains the label and the clause dropdown
|
||||
// and we have one span for ON DELETE and one for ON UPDATE
|
||||
//
|
||||
if ($thisDropdown.val() !== '') {
|
||||
$thisDropdown.parent().nextAll('span').show();
|
||||
} else {
|
||||
if ($thisDropdown.val() == '') {
|
||||
$thisDropdown.parent().nextAll('span').hide();
|
||||
} else {
|
||||
if ($thisDropdown.is('select[name^="destination_foreign_column"]')) {
|
||||
$thisDropdown.parent().nextAll('span').show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and populates dropdowns to the left based on the selected value
|
||||
*
|
||||
* @param $dropdown the dropdown whose value got changed
|
||||
*/
|
||||
function getDropdownValues($dropdown) {
|
||||
var foreignDb = null, foreignTable = null;
|
||||
var $tableDd, $columnDd;
|
||||
var foreign = '';
|
||||
// if the changed dropdown is for foreign key constraints
|
||||
if ($dropdown.is('select[name^="destination_foreign"]')) {
|
||||
$tableDd = $dropdown.parent().find('select[name^="destination_foreign_table"]');
|
||||
$columnDd = $dropdown.parent().find('select[name^="destination_foreign_column"]');
|
||||
foreign = '_foreign';
|
||||
} else { // internal relations
|
||||
$tableDd = $dropdown.parent().find('select[name^="destination_table"]');
|
||||
$columnDd = $dropdown.parent().find('select[name^="destination_column"]');
|
||||
}
|
||||
|
||||
// if the changed dropdown is a database selector
|
||||
if ($dropdown.is('select[name^="destination' + foreign + '_db"]')) {
|
||||
foreignDb = $dropdown.val();
|
||||
// if no database is selected empty table and column dropdowns
|
||||
if (foreignDb == '') {
|
||||
setDropdownValues($tableDd, []);
|
||||
setDropdownValues($columnDd, []);
|
||||
return;
|
||||
}
|
||||
} else { // if a table selector
|
||||
foreignDb = $dropdown.parent()
|
||||
.find('select[name^="destination' + foreign + '_db"]').val();
|
||||
foreignTable = $dropdown.val();
|
||||
// if no table is selected empty the column dropdown
|
||||
if (foreignTable == '') {
|
||||
setDropdownValues($columnDd, []);
|
||||
return;
|
||||
}
|
||||
}
|
||||
var $msgbox = PMA_ajaxShowMessage();
|
||||
var $form = $dropdown.parents('form');
|
||||
var url = 'tbl_relation.php?getDropdownValues=true&ajax_request=true'
|
||||
+ '&token=' + $form.find('input[name="token"]').val()
|
||||
+ '&db=' + $form.find('input[name="db"]').val()
|
||||
+ '&table=' + $form.find('input[name="table"]').val()
|
||||
+ '&foreign=' + (foreign != '')
|
||||
+ '&foreignDb=' + encodeURIComponent(foreignDb)
|
||||
+ (foreignTable !== null ?
|
||||
'&foreignTable=' + encodeURIComponent(foreignTable) : ''
|
||||
);
|
||||
$.ajax({
|
||||
url: url,
|
||||
datatype: 'json',
|
||||
success: function(data) {
|
||||
PMA_ajaxRemoveMessage($msgbox);
|
||||
if (data.success) {
|
||||
// if the changed dropdown is a database selector
|
||||
if (foreignTable == null) {
|
||||
// set values for table and column dropdowns
|
||||
setDropdownValues($tableDd, data.tables);
|
||||
setDropdownValues($columnDd, []);
|
||||
} else { // if a table selector
|
||||
// set values for the column dropdown
|
||||
setDropdownValues($columnDd, data.columns);
|
||||
}
|
||||
} else {
|
||||
PMA_ajaxShowMessage(data.error, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setDropdownValues($dropdown, values) {
|
||||
$dropdown.empty();
|
||||
var optionsAsString = '';
|
||||
// add an empty string to the beginning for empty selection
|
||||
values.unshift('');
|
||||
$.each(values, function() {
|
||||
optionsAsString += "<option value='" + this + "'>" + this + "</option>";
|
||||
})
|
||||
$dropdown.append($(optionsAsString));
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbind all event handlers before tearing down a page
|
||||
*/
|
||||
AJAX.registerTeardown('tbl_relation.js', function () {
|
||||
$('select.referenced_column_dropdown').unbind('change');
|
||||
$('select[name^="destination_foreign"]').unbind('change');
|
||||
$('select[name^="destination_db"],'
|
||||
+ ' select[name^="destination_table"],'
|
||||
+ ' select[name^="destination_foreign_db"],'
|
||||
+ ' select[name^="destination_foreign_table"]').unbind('change');
|
||||
});
|
||||
|
||||
AJAX.registerOnload('tbl_relation.js', function () {
|
||||
// initial display
|
||||
$('select.referenced_column_dropdown').each(function (index, one_dropdown) {
|
||||
$('select[name^="destination_foreign_column"]').each(function (index, one_dropdown) {
|
||||
show_hide_clauses($(one_dropdown));
|
||||
});
|
||||
// change
|
||||
$('select.referenced_column_dropdown').change(function () {
|
||||
$('select[name^="destination_foreign"]').change(function () {
|
||||
show_hide_clauses($(this));
|
||||
});
|
||||
|
||||
$('select[name^="destination_db"],'
|
||||
+ ' select[name^="destination_table"],'
|
||||
+ ' select[name^="destination_foreign_db"],'
|
||||
+ ' select[name^="destination_foreign_table"]')
|
||||
.change(function() {
|
||||
getDropdownValues($(this));
|
||||
});
|
||||
});
|
||||
|
||||
@ -1314,10 +1314,11 @@ class PMA_Table
|
||||
* - UNIQUE(x,y) // NONE
|
||||
*
|
||||
* @param bool $backquoted whether to quote name with backticks ``
|
||||
* @param bool $fullName whether to include full name of the table as a prefix
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getUniqueColumns($backquoted = true)
|
||||
public function getUniqueColumns($backquoted = true, $fullName = true)
|
||||
{
|
||||
$sql = $GLOBALS['dbi']->getTableIndexesSql(
|
||||
$this->getDbName(),
|
||||
@ -1335,7 +1336,7 @@ class PMA_Table
|
||||
if (count($index) > 1) {
|
||||
continue;
|
||||
}
|
||||
$return[] = $this->getFullName($backquoted) . '.'
|
||||
$return[] = ($fullName ? $this->getFullName($backquoted) . '.' : '')
|
||||
. ($backquoted ? PMA_Util::backquote($index[0]) : $index[0]);
|
||||
}
|
||||
|
||||
|
||||
@ -1427,8 +1427,8 @@ function PMA_getHtmlForReferentialIntegrityCheck($foreign, $url_params)
|
||||
. '<a href="sql.php'
|
||||
. PMA_generate_common_url($this_url_params)
|
||||
. '">'
|
||||
. $master . ' -> ' . $arr['foreign_table'] . '.'
|
||||
. $arr['foreign_field']
|
||||
. $master . ' -> ' . $arr['foreign_db'] . '.'
|
||||
. $arr['foreign_table'] . '.' . $arr['foreign_field']
|
||||
. '</a></li>' . "\n";
|
||||
} // foreach $foreign
|
||||
$html_output .= '</ul></fieldset></div>';
|
||||
|
||||
@ -88,9 +88,9 @@ function PMA_getSQLToDropForeignKey($table, $fk)
|
||||
*
|
||||
* @param string $table table name
|
||||
* @param string $field field name
|
||||
* @param string $foreignDb back-quoted foreign database name
|
||||
* @param string $foreignTable back-quoted foreign table name
|
||||
* @param string $foreignField back-quoted foreign field name
|
||||
* @param string $foreignDb foreign database name
|
||||
* @param string $foreignTable foreign table name
|
||||
* @param string $foreignField foreign field name
|
||||
* @param string $name name of the constraint
|
||||
* @param string $onDelete on delete action
|
||||
* @param string $onUpdate on update action
|
||||
@ -107,8 +107,9 @@ function PMA_getSQLToCreateForeignKey($table, $field, $foreignDb, $foreignTable,
|
||||
}
|
||||
|
||||
$sql_query .= ' FOREIGN KEY (' . PMA_Util::backquote($field) . ')'
|
||||
. ' REFERENCES ' . $foreignDb . '.' . $foreignTable
|
||||
. '(' . $foreignField . ')';
|
||||
. ' REFERENCES ' . PMA_Util::backquote($foreignDb)
|
||||
. '.' . PMA_Util::backquote($foreignTable)
|
||||
. '(' . PMA_Util::backquote($foreignField) . ')';
|
||||
|
||||
if (! empty($onDelete)) {
|
||||
$sql_query .= ' ON DELETE ' . $onDelete;
|
||||
@ -120,4 +121,36 @@ function PMA_getSQLToCreateForeignKey($table, $field, $foreignDb, $foreignTable,
|
||||
|
||||
return $sql_query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and populates dropdowns to select foreign db/table/column
|
||||
*
|
||||
* @param string $name name of the dropdowns
|
||||
* @param array $values dropdown values
|
||||
* @param string $foreign value of the item to be selected
|
||||
*
|
||||
* @return string HTML for the dropdown
|
||||
*/
|
||||
function PMA_generateRelationalDropdown($name, $values = array(), $foreign = false)
|
||||
{
|
||||
$html_output = '<select name="' . $name . '">';
|
||||
$html_output .= '<option value=""></option>';
|
||||
|
||||
$seen_key = false;
|
||||
foreach ($values as $value) {
|
||||
$html_output .= '<option value="' . htmlspecialchars($value) . '"';
|
||||
if ($foreign && $value == $foreign) {
|
||||
$html_output .= ' selected="selected"';
|
||||
$seen_key = true;
|
||||
}
|
||||
$html_output .= '>' . htmlspecialchars($value) . '</option>';
|
||||
}
|
||||
|
||||
if ($foreign && ! $seen_key) {
|
||||
$html_output .= '<option value="' . htmlspecialchars($foreign) . '"'
|
||||
. ' selected="selected">' . htmlspecialchars($foreign) . '</option>';
|
||||
}
|
||||
$html_output .= '</select>';
|
||||
return $html_output;
|
||||
}
|
||||
?>
|
||||
|
||||
353
tbl_relation.php
353
tbl_relation.php
@ -9,8 +9,6 @@
|
||||
* 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 add an link to create an index required for constraints,
|
||||
* or an option to do automatically
|
||||
* @todo if above todos are fullfilled we can add all fields meet requirements
|
||||
* in the select dropdown
|
||||
* @package PhpMyAdmin
|
||||
@ -24,6 +22,59 @@ require_once 'libraries/index.lib.php';
|
||||
require_once 'libraries/tbl_relation.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'
|
||||
) {
|
||||
$foreignDb = $_REQUEST['foreignDb'];
|
||||
|
||||
if (isset($_REQUEST['foreignTable'])) { // if both db and table are selected
|
||||
$foreignTable = $_REQUEST['foreignTable'];
|
||||
$table_obj = new PMA_Table($foreignTable, $foreignDb);
|
||||
$columns = array();
|
||||
foreach ($table_obj->getUniqueColumns(false, false) as $column) {
|
||||
$columns[] = htmlspecialchars($column);
|
||||
}
|
||||
$response->addJSON('columns', $columns);
|
||||
|
||||
} else { // if only the db is selected
|
||||
$foreign = isset($_REQUEST['foreign']) && $_REQUEST['foreign'] === 'true';
|
||||
if ($foreign) {
|
||||
$query = 'SHOW TABLE STATUS FROM ' . PMA_Util::backquote($foreignDb);
|
||||
$tbl_storage_engine = strtoupper(
|
||||
PMA_Table::sGetStatusInfo(
|
||||
$_REQUEST['db'],
|
||||
$_REQUEST['table'],
|
||||
'Engine'
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$query = 'SHOW TABLES FROM ' . PMA_Util::backquote($foreignDb);
|
||||
}
|
||||
$tables_rs = $GLOBALS['dbi']->query(
|
||||
$query,
|
||||
null,
|
||||
PMA_DatabaseInterface::QUERY_STORE
|
||||
);
|
||||
$tables = array();
|
||||
while ($row = $GLOBALS['dbi']->fetchRow($tables_rs)) {
|
||||
if ($foreign) {
|
||||
if (isset($row[1])
|
||||
&& strtoupper($row[1]) == $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');
|
||||
@ -33,8 +84,12 @@ $scripts->addFile('indexes.js');
|
||||
* Sets globals from $_POST
|
||||
*/
|
||||
$post_params = array(
|
||||
'destination',
|
||||
'destination_foreign',
|
||||
'destination_db',
|
||||
'destination_table',
|
||||
'destination_column',
|
||||
'destination_foreign_db',
|
||||
'destination_foreign_table',
|
||||
'destination_foreign_column',
|
||||
'display_field',
|
||||
'fields_name',
|
||||
'on_delete',
|
||||
@ -85,18 +140,20 @@ $multi_edit_columns_name = isset($_REQUEST['fields_name'])
|
||||
$html_output = '';
|
||||
|
||||
// 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($destination) && $cfgRelation['relwork']) {
|
||||
if (isset($destination_db) && $cfgRelation['relwork']) {
|
||||
|
||||
foreach ($destination as $master_field_md5 => $foreign_string) {
|
||||
foreach ($destination_db as $master_field_md5 => $foreign_db) {
|
||||
$upd_query = false;
|
||||
|
||||
// Map the fieldname's md5 back to its real name
|
||||
$master_field = $multi_edit_columns_name[$master_field_md5];
|
||||
|
||||
if (! empty($foreign_string)) {
|
||||
$foreign_string = trim($foreign_string, '`');
|
||||
list($foreign_db, $foreign_table, $foreign_field)
|
||||
= explode('.', $foreign_string);
|
||||
$foreign_table = $destination_table[$master_field_md5];
|
||||
$foreign_field = $destination_column[$master_field_md5];
|
||||
if (! empty($foreign_db)
|
||||
&& ! empty($foreign_table)
|
||||
&& ! empty($foreign_field)
|
||||
) {
|
||||
if (! isset($existrel[$master_field])) {
|
||||
$upd_query = 'INSERT INTO '
|
||||
. PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
|
||||
@ -110,7 +167,11 @@ if (isset($destination) && $cfgRelation['relwork']) {
|
||||
. '\'' . PMA_Util::sqlAddSlashes($foreign_db) . '\', '
|
||||
. '\'' . PMA_Util::sqlAddSlashes($foreign_table) . '\','
|
||||
. '\'' . PMA_Util::sqlAddSlashes($foreign_field) . '\')';
|
||||
} elseif ($existrel[$master_field]['foreign_db'] . '.' .$existrel[$master_field]['foreign_table'] . '.' . $existrel[$master_field]['foreign_field'] != $foreign_string) {
|
||||
|
||||
} elseif ($existrel[$master_field]['foreign_db'] != $foreign_db
|
||||
|| $existrel[$master_field]['foreign_table'] != $foreign_table
|
||||
|| $existrel[$master_field]['foreign_field'] != $foreign_field
|
||||
) {
|
||||
$upd_query = 'UPDATE '
|
||||
. PMA_Util::backquote($GLOBALS['cfgRelation']['db'])
|
||||
. '.' . PMA_Util::backquote($cfgRelation['relation']) . ' SET'
|
||||
@ -120,7 +181,8 @@ if (isset($destination) && $cfgRelation['relwork']) {
|
||||
. PMA_Util::sqlAddSlashes($foreign_table) . '\', '
|
||||
. ' foreign_field = \''
|
||||
. PMA_Util::sqlAddSlashes($foreign_field) . '\' '
|
||||
. ' WHERE master_db = \'' . PMA_Util::sqlAddSlashes($db) . '\''
|
||||
. ' WHERE master_db = \''
|
||||
. PMA_Util::sqlAddSlashes($db) . '\''
|
||||
. ' AND master_table = \''
|
||||
. PMA_Util::sqlAddSlashes($table) . '\''
|
||||
. ' AND master_field = \''
|
||||
@ -145,25 +207,28 @@ if (isset($destination) && $cfgRelation['relwork']) {
|
||||
// (for now, one index name only; we keep the definitions if the
|
||||
// foreign db is not the same)
|
||||
|
||||
if (isset($_REQUEST['destination_foreign'])) {
|
||||
if (isset($destination_foreign_db)) {
|
||||
$display_query = '';
|
||||
$seen_error = false;
|
||||
foreach ($_REQUEST['destination_foreign'] as $master_field_md5 => $foreign_string) {
|
||||
foreach ($destination_foreign_db as $master_field_md5 => $foreign_db) {
|
||||
$create = false;
|
||||
$drop = false;
|
||||
|
||||
// Map the fieldname's md5 back to it's real name
|
||||
$master_field = $multi_edit_columns_name[$master_field_md5];
|
||||
|
||||
if (! empty($foreign_string)) {
|
||||
list($foreign_db, $foreign_table, $foreign_field)
|
||||
= PMA_backquoteSplit($foreign_string);
|
||||
$foreign_table = $destination_foreign_table[$master_field_md5];
|
||||
$foreign_field = $destination_foreign_column[$master_field_md5];
|
||||
if (! empty($foreign_db)
|
||||
&& ! empty($foreign_table)
|
||||
&& ! empty($foreign_field)
|
||||
) {
|
||||
if (! isset($existrel_foreign[$master_field])) {
|
||||
// no key defined for this field
|
||||
$create = true;
|
||||
} elseif (PMA_Util::backquote($existrel_foreign[$master_field]['foreign_db']) != $foreign_db
|
||||
|| PMA_Util::backquote($existrel_foreign[$master_field]['foreign_table']) != $foreign_table
|
||||
|| PMA_Util::backquote($existrel_foreign[$master_field]['foreign_field']) != $foreign_field
|
||||
} elseif ($existrel_foreign[$master_field]['foreign_db'] != $foreign_db
|
||||
|| $existrel_foreign[$master_field]['foreign_table'] != $foreign_table
|
||||
|| $existrel_foreign[$master_field]['foreign_field'] != $foreign_field
|
||||
|| $_REQUEST['constraint_name'][$master_field_md5] != $existrel_foreign[$master_field]['constraint']
|
||||
|| ($_REQUEST['on_delete'][$master_field_md5] != (! empty($existrel_foreign[$master_field]['on_delete']) ? $existrel_foreign[$master_field]['on_delete'] : 'RESTRICT'))
|
||||
|| ($_REQUEST['on_update'][$master_field_md5] != (! empty($existrel_foreign[$master_field]['on_update']) ? $existrel_foreign[$master_field]['on_update'] : 'RESTRICT'))
|
||||
@ -233,10 +298,11 @@ if (isset($_REQUEST['destination_foreign'])) {
|
||||
// a rollback may be better here
|
||||
$sql_query_recreate = '# Restoring the dropped constraint...' . "\n";
|
||||
$sql_query_recreate .= PMA_getSQLToCreateForeignKey(
|
||||
$table, $master_field,
|
||||
PMA_Util::backquote($existrel_foreign[$master_field]['foreign_db']),
|
||||
PMA_Util::backquote($existrel_foreign[$master_field]['foreign_table']),
|
||||
PMA_Util::backquote($existrel_foreign[$master_field]['foreign_field']),
|
||||
$table,
|
||||
$master_field,
|
||||
$existrel_foreign[$master_field]['foreign_db'],
|
||||
$existrel_foreign[$master_field]['foreign_table'],
|
||||
$existrel_foreign[$master_field]['foreign_field'],
|
||||
$existrel_foreign[$master_field]['constraint'],
|
||||
$options_array[$existrel_foreign[$master_field]['on_delete']],
|
||||
$options_array[$existrel_foreign[$master_field]['on_update']]
|
||||
@ -291,10 +357,10 @@ if ($cfgRelation['displaywork'] && isset($display_field)) {
|
||||
} // end if
|
||||
|
||||
// If we did an update, refresh our data
|
||||
if (isset($destination) && $cfgRelation['relwork']) {
|
||||
if (isset($destination_db) && $cfgRelation['relwork']) {
|
||||
$existrel = PMA_getForeigners($db, $table, '', 'internal');
|
||||
}
|
||||
if (isset($destination_foreign)
|
||||
if (isset($destination_foreign_db)
|
||||
&& PMA_Util::isForeignKeySupported($tbl_storage_engine)
|
||||
) {
|
||||
$existrel_foreign = PMA_getForeigners($db, $table, '', 'foreign');
|
||||
@ -313,57 +379,6 @@ if ($cfgRelation['displaywork']) {
|
||||
$html_output .= '<form method="post" action="tbl_relation.php">' . "\n"
|
||||
. PMA_generate_common_hidden_inputs($db, $table);
|
||||
|
||||
|
||||
// relations
|
||||
|
||||
if ($cfgRelation['relwork']
|
||||
|| PMA_Util::isForeignKeySupported($tbl_storage_engine)
|
||||
) {
|
||||
// To choose relations we first need all tables names in current db
|
||||
// and if the main table supports foreign keys
|
||||
// we use SHOW TABLE STATUS because we need to find other tables of the
|
||||
// same engine.
|
||||
|
||||
if (PMA_Util::isForeignKeySupported($tbl_storage_engine)) {
|
||||
$tab_query = 'SHOW TABLE STATUS FROM ' . PMA_Util::backquote($db);
|
||||
// [0] of the row is the name
|
||||
// [1] is the type
|
||||
} else {
|
||||
$tab_query = 'SHOW TABLES FROM ' . PMA_Util::backquote($db);
|
||||
// [0] of the row is the name
|
||||
}
|
||||
|
||||
$tab_rs = $GLOBALS['dbi']->query(
|
||||
$tab_query, null, PMA_DatabaseInterface::QUERY_STORE
|
||||
);
|
||||
$selectboxall[] = '';
|
||||
$selectboxall_foreign[] = '';
|
||||
|
||||
while ($curr_table = $GLOBALS['dbi']->fetchRow($tab_rs)) {
|
||||
$current_table = new PMA_Table($curr_table[0], $db);
|
||||
|
||||
// explicitely ask for non-quoted list of indexed columns
|
||||
$selectboxall = array_merge(
|
||||
$selectboxall,
|
||||
$current_table->getUniqueColumns($backquoted = false)
|
||||
);
|
||||
|
||||
// if foreign keys are supported, collect all keys from other
|
||||
// tables of the same engine
|
||||
if (PMA_Util::isForeignKeySupported($tbl_storage_engine)
|
||||
&& isset($curr_table[1])
|
||||
&& strtoupper($curr_table[1]) == $tbl_storage_engine
|
||||
) {
|
||||
// explicitely ask for non-quoted list of indexed columns
|
||||
// need to obtain backquoted values to support dots inside values
|
||||
$selectboxall_foreign = array_merge(
|
||||
$selectboxall_foreign,
|
||||
$current_table->getIndexedColumns($backquoted = true)
|
||||
);
|
||||
}
|
||||
} // end while over tables
|
||||
} // end if
|
||||
|
||||
// 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);
|
||||
@ -377,7 +392,7 @@ if (count($columns) > 0) {
|
||||
$saved_row_cnt = count($save_row);
|
||||
$html_output .= '<fieldset>'
|
||||
. '<legend>' . __('Relations'). '</legend>'
|
||||
. '<table>'
|
||||
. '<table id="relationalTable">'
|
||||
. '<tr><th>' . __('Column') . '</th>';
|
||||
|
||||
if ($cfgRelation['relwork']) {
|
||||
@ -418,84 +433,133 @@ if (count($columns) > 0) {
|
||||
$odd_row = ! $odd_row;
|
||||
|
||||
if ($cfgRelation['relwork']) {
|
||||
$html_output .= '<td><select name="destination[' . $myfield_md5 . ']">';
|
||||
// PMA internal relations
|
||||
if (isset($existrel[$myfield])) {
|
||||
$foreign_field = $existrel[$myfield]['foreign_db'] . '.'
|
||||
. $existrel[$myfield]['foreign_table'] . '.'
|
||||
. $existrel[$myfield]['foreign_field'];
|
||||
} else {
|
||||
$foreign_field = false;
|
||||
}
|
||||
$seen_key = false;
|
||||
foreach ($selectboxall as $value) {
|
||||
$html_output .= '<option value="' . htmlspecialchars($value) . '"';
|
||||
if ($foreign_field && $value == $foreign_field) {
|
||||
$html_output .= ' selected="selected"';
|
||||
$seen_key = true;
|
||||
}
|
||||
$html_output .= '>' . htmlspecialchars($value) . '</option>'. "\n";
|
||||
} // end while
|
||||
$html_output .= '<td>';
|
||||
|
||||
// if the link defined in relationtable points to a foreign field
|
||||
// that is not a key in the foreign table, we show the link
|
||||
// (will not be shown with an arrow)
|
||||
if ($foreign_field && !$seen_key) {
|
||||
$html_output .= '<option value="' . htmlspecialchars($foreign_field)
|
||||
. '"'
|
||||
. ' selected="selected">' . $foreign_field . '</option>'. "\n";
|
||||
$foreign_db = false;
|
||||
$foreign_table = false;
|
||||
$foreign_column = false;
|
||||
|
||||
// database dropdown
|
||||
if (isset($existrel[$myfield])) {
|
||||
$foreign_db = $existrel[$myfield]['foreign_db'];
|
||||
} else {
|
||||
$foreign_db = $db;
|
||||
}
|
||||
$html_output .= '</select>'
|
||||
. '</td>';
|
||||
$html_output .= PMA_generateRelationalDropdown(
|
||||
'destination_db[' . $myfield_md5 . ']',
|
||||
$GLOBALS['pma']->databases,
|
||||
$foreign_db
|
||||
);
|
||||
// end of database dropdown
|
||||
|
||||
// table dropdown
|
||||
$tables = array();
|
||||
if ($foreign_db) {
|
||||
if (isset($existrel[$myfield])) {
|
||||
$foreign_table = $existrel[$myfield]['foreign_table'];
|
||||
}
|
||||
$tables_rs = $GLOBALS['dbi']->query(
|
||||
'SHOW TABLES FROM ' . PMA_Util::backquote($foreign_db),
|
||||
null,
|
||||
PMA_DatabaseInterface::QUERY_STORE
|
||||
);
|
||||
while ($row = $GLOBALS['dbi']->fetchRow($tables_rs)) {
|
||||
$tables[] = $row[0];
|
||||
}
|
||||
}
|
||||
$html_output .= PMA_generateRelationalDropdown(
|
||||
'destination_table[' . $myfield_md5 . ']',
|
||||
$tables,
|
||||
$foreign_table
|
||||
);
|
||||
// end of table dropdown
|
||||
|
||||
// column dropdown
|
||||
$columns = array();
|
||||
if ($foreign_db && $foreign_table) {
|
||||
if (isset($existrel[$myfield])) {
|
||||
$foreign_column = $existrel[$myfield]['foreign_field'];
|
||||
}
|
||||
$table_obj = new PMA_Table($foreign_table, $foreign_db);
|
||||
$columns = $table_obj->getUniqueColumns(false, false);
|
||||
}
|
||||
$html_output .= PMA_generateRelationalDropdown(
|
||||
'destination_column[' . $myfield_md5 . ']',
|
||||
$columns,
|
||||
$foreign_column
|
||||
);
|
||||
// end of column dropdown
|
||||
|
||||
$html_output .= '</td>';
|
||||
} // end if (internal relations)
|
||||
|
||||
if (PMA_Util::isForeignKeySupported($tbl_storage_engine)) {
|
||||
$html_output .= '<td>';
|
||||
if (!empty($save_row[$i]['Key'])) {
|
||||
$html_output .= '<span class="formelement">'
|
||||
. '<select name="destination_foreign[' . $myfield_md5 . ']"'
|
||||
. ' class="referenced_column_dropdown">';
|
||||
if (! empty($save_row[$i]['Key'])) {
|
||||
|
||||
$foreign_db = false;
|
||||
$foreign_table = false;
|
||||
$foreign_column = false;
|
||||
|
||||
// foreign database dropdown
|
||||
if (isset($existrel_foreign[$myfield])) {
|
||||
// need to PMA_Util::backquote to support a dot character inside
|
||||
// an element
|
||||
$foreign_field = PMA_Util::backquote(
|
||||
$existrel_foreign[$myfield]['foreign_db']
|
||||
)
|
||||
. '.' . PMA_Util::backquote(
|
||||
$existrel_foreign[$myfield]['foreign_table']
|
||||
)
|
||||
. '.' . PMA_Util::backquote(
|
||||
$existrel_foreign[$myfield]['foreign_field']
|
||||
);
|
||||
$foreign_db = $existrel_foreign[$myfield]['foreign_db'];
|
||||
} else {
|
||||
$foreign_field = false;
|
||||
$foreign_db = $db;
|
||||
}
|
||||
$html_output .= '<span class="formelement clearfloat">';
|
||||
$html_output .= PMA_generateRelationalDropdown(
|
||||
'destination_foreign_db[' . $myfield_md5 . ']',
|
||||
$GLOBALS['pma']->databases,
|
||||
$foreign_db
|
||||
);
|
||||
// end of foreign database dropdown
|
||||
|
||||
$found_foreign_field = false;
|
||||
foreach ($selectboxall_foreign as $value) {
|
||||
$html_output .= '<option value="'
|
||||
. htmlspecialchars($value) . '"';
|
||||
if ($foreign_field && $value == $foreign_field) {
|
||||
$html_output .= ' selected="selected"';
|
||||
$found_foreign_field = true;
|
||||
// foreign table dropdown
|
||||
$tables = array();
|
||||
if ($foreign_db) {
|
||||
if (isset($existrel_foreign[$myfield])) {
|
||||
$foreign_table = $existrel_foreign[$myfield]['foreign_table'];
|
||||
}
|
||||
$tables_rs = $GLOBALS['dbi']->query(
|
||||
'SHOW TABLE STATUS FROM ' . PMA_Util::backquote($foreign_db),
|
||||
null,
|
||||
PMA_DatabaseInterface::QUERY_STORE
|
||||
);
|
||||
while ($row = $GLOBALS['dbi']->fetchRow($tables_rs)) {
|
||||
if (isset($row[1])
|
||||
&& strtoupper($row[1]) == $tbl_storage_engine
|
||||
) {
|
||||
$tables[] = $row[0];
|
||||
}
|
||||
}
|
||||
$html_output .= '>' . htmlspecialchars($value)
|
||||
. '</option>'. "\n";
|
||||
} // end while
|
||||
|
||||
// we did not find the foreign field in the tables of current db,
|
||||
// must be defined in another db so show it to avoid erasing it
|
||||
if (!$found_foreign_field && $foreign_field) {
|
||||
$html_output .= '<option value="'
|
||||
. htmlspecialchars($foreign_field) . '"'
|
||||
. ' selected="selected"'
|
||||
. '>' . $foreign_field . '</option>' . "\n";
|
||||
}
|
||||
$html_output .= '</select>'
|
||||
. '</span>';
|
||||
$html_output .= PMA_generateRelationalDropdown(
|
||||
'destination_foreign_table[' . $myfield_md5 . ']',
|
||||
$tables,
|
||||
$foreign_table
|
||||
);
|
||||
// end of foreign table dropdown
|
||||
|
||||
// foreign column dropdown
|
||||
$columns = array();
|
||||
if ($foreign_db && $foreign_table) {
|
||||
if (isset($existrel_foreign[$myfield])) {
|
||||
$foreign_column = $existrel_foreign[$myfield]['foreign_field'];
|
||||
}
|
||||
$table_obj = new PMA_Table($foreign_table, $foreign_db);
|
||||
$columns = $table_obj->getUniqueColumns(false, false);
|
||||
}
|
||||
$html_output .= PMA_generateRelationalDropdown(
|
||||
'destination_foreign_column[' . $myfield_md5 . ']',
|
||||
$columns,
|
||||
$foreign_column
|
||||
);
|
||||
$html_output .= '</span>';
|
||||
// end of foreign column dropdown
|
||||
|
||||
// For constraint name
|
||||
$html_output .= '<span class="formelement">';
|
||||
$html_output .= '<span class="formelement clearfloat">';
|
||||
$constraint_name = isset($existrel_foreign[$myfield]['constraint'])
|
||||
? $existrel_foreign[$myfield]['constraint'] : '';
|
||||
$html_output .= __('Constraint name');
|
||||
@ -504,7 +568,7 @@ if (count($columns) > 0) {
|
||||
. ' value="' . $constraint_name . '"/>';
|
||||
$html_output .= '</span>' . "\n";
|
||||
|
||||
$html_output .= '<span class="formelement">';
|
||||
$html_output .= '<span class="formelement clearfloat">';
|
||||
// For ON DELETE and ON UPDATE, the default action
|
||||
// is RESTRICT as per MySQL doc; however, a SHOW CREATE TABLE
|
||||
// won't display the clause if it's set as RESTRICT.
|
||||
@ -518,7 +582,7 @@ if (count($columns) > 0) {
|
||||
);
|
||||
$html_output .= '</span>' . "\n";
|
||||
|
||||
$html_output .= '<span class="formelement">' . "\n";
|
||||
$html_output .= '<span class="formelement clearfloat">' . "\n";
|
||||
$on_update = isset($existrel_foreign[$myfield]['on_update'])
|
||||
? $existrel_foreign[$myfield]['on_update'] : 'RESTRICT';
|
||||
$html_output .= PMA_generateDropdown(
|
||||
@ -574,5 +638,4 @@ if (PMA_Util::isForeignKeySupported($tbl_storage_engine)) {
|
||||
}
|
||||
// Render HTML output
|
||||
PMA_Response::getInstance()->addHTML($html_output);
|
||||
|
||||
?>
|
||||
|
||||
@ -2572,3 +2572,8 @@ div.jqplot-noData-container {
|
||||
text-align: center;
|
||||
background-color: rgba(96%, 96%, 96%, 0.3);
|
||||
}
|
||||
|
||||
#relationalTable select {
|
||||
width: 125px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
@ -2778,6 +2778,11 @@ fieldset .disabled-field td {
|
||||
padding-<?php echo $left; ?>: 20px;
|
||||
}
|
||||
|
||||
#relationalTable select {
|
||||
width: 125px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
/* css for timepicker */
|
||||
.ui-timepicker-div .ui-widget-header { margin-bottom: 8px; }
|
||||
.ui-timepicker-div dl { text-align: <?php echo $left; ?>; }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user