Select from foreign keys in Editor

git-svn-id: https://adminer.svn.sourceforge.net/svnroot/adminer/trunk@883 7c3ca157-0c34-0410-bff1-cbf682f78f5c
This commit is contained in:
jakubvrana 2009-07-23 14:42:38 +00:00
parent f13efa8684
commit 1e4d11e920
7 changed files with 109 additions and 53 deletions

View file

@ -57,7 +57,7 @@ if ($in) {
if (strlen($value) && ($field["type"] == "enum" || $field["type"] == "set")) { if (strlen($value) && ($field["type"] == "enum" || $field["type"] == "set")) {
$value = intval($value); $value = intval($value);
} }
input($key, $field, $value, (string) $_POST["function"][$name]); // param name can be empty input($field, $value, (string) $_POST["function"][$name]); // param name can be empty
echo "\n"; echo "\n";
} }
echo "</table>\n"; echo "</table>\n";

View file

@ -79,7 +79,7 @@ if ($fields) {
: ($_POST["clone"] && $field["auto_increment"] ? "" : (isset($_GET["select"]) ? false : $field["default"])) : ($_POST["clone"] && $field["auto_increment"] ? "" : (isset($_GET["select"]) ? false : $field["default"]))
); );
$function = ($_POST["save"] ? (string) $_POST["function"][$name] : ($where && $field["on_update"] == "CURRENT_TIMESTAMP" ? "now" : ($value === false ? null : (isset($value) ? '' : 'NULL')))); $function = ($_POST["save"] ? (string) $_POST["function"][$name] : ($where && $field["on_update"] == "CURRENT_TIMESTAMP" ? "now" : ($value === false ? null : (isset($value) ? '' : 'NULL'))));
input($name, $field, $value, $function); input($field, $value, $function);
if (isset($_GET["default"]) && $field["type"] == "timestamp") { if (isset($_GET["default"]) && $field["type"] == "timestamp") {
if (!isset($create) && !$_POST) { if (!isset($create) && !$_POST) {
//! disable sql_mode NO_FIELD_OPTIONS //! disable sql_mode NO_FIELD_OPTIONS

View file

@ -90,9 +90,17 @@ function adminer_select_query($query) {
return call_adminer('select_query', "<p><code class='jush-sql'>" . htmlspecialchars($query) . "</code> <a href='" . htmlspecialchars($SELF) . "sql=" . urlencode($query) . "'>" . lang('Edit') . "</a>\n", $query); return call_adminer('select_query', "<p><code class='jush-sql'>" . htmlspecialchars($query) . "</code> <a href='" . htmlspecialchars($SELF) . "sql=" . urlencode($query) . "'>" . lang('Edit') . "</a>\n", $query);
} }
/** Descriptions of selected data /** Description of a row in a table
* @param string
* @return string SQL expression, empty string for no description
*/
function adminer_row_description($table) {
return call_adminer('row_description', "", $table);
}
/** Get descriptions of selected data
* @param array all data to print * @param array all data to print
* @param array foreign keys * @param array
* @return array * @return array
*/ */
function adminer_row_descriptions($rows, $foreign_keys) { function adminer_row_descriptions($rows, $foreign_keys) {
@ -147,7 +155,16 @@ function adminer_edit_functions($field) {
if ($field["null"] || isset($_GET["default"])) { if ($field["null"] || isset($_GET["default"])) {
array_unshift($return, "NULL"); array_unshift($return, "NULL");
} }
return call_adminer('edit_functions', $return, $field); return call_adminer('edit_functions', (isset($_GET["select"]) ? array("orig" => lang('original')) : array()) + $return, $field);
}
/** Get options to display edit field
* @param string table name
* @param array single field from fields()
* @return array options for <select> or empty to display <input>
*/
function adminer_edit_input($table, $field) {
return call_adminer('edit_input', false, $table, $field);
} }
/** Prints navigation after Adminer title /** Prints navigation after Adminer title

View file

@ -13,14 +13,14 @@ function bracket_escape($idf, $back = false) {
return strtr($idf, ($back ? array_flip($trans) : $trans)); return strtr($idf, ($back ? array_flip($trans) : $trans));
} }
function optionlist($options, $selected = null) { function optionlist($options, $selected = null, $use_keys = false) {
$return = ""; $return = "";
foreach ($options as $k => $v) { foreach ($options as $k => $v) {
if (is_array($v)) { if (is_array($v)) {
$return .= '<optgroup label="' . htmlspecialchars($k) . '">'; $return .= '<optgroup label="' . htmlspecialchars($k) . '">';
} }
foreach ((is_array($v) ? $v : array($k => $v)) as $key => $val) { foreach ((is_array($v) ? $v : array($k => $v)) as $key => $val) {
$return .= '<option' . (is_string($key) ? ' value="' . htmlspecialchars($key) . '"' : '') . ((is_string($key) ? $key : $val) === $selected ? ' selected="selected"' : '') . '>' . htmlspecialchars($val); $return .= '<option' . ($use_keys || is_string($key) ? ' value="' . htmlspecialchars($key) . '"' : '') . (($use_keys || is_string($key) ? (string) $key : $val) === $selected ? ' selected="selected"' : '') . '>' . htmlspecialchars($val);
} }
if (is_array($v)) { if (is_array($v)) {
$return .= '</optgroup>'; $return .= '</optgroup>';
@ -265,9 +265,19 @@ function hidden_fields($process, $ignore = array()) {
} }
} }
function input($name, $field, $value, $function) { function column_foreign_keys($table) {
$return = array();
foreach (foreign_keys($table) as $foreign_key) {
foreach ($foreign_key["source"] as $val) {
$return[$val][] = $foreign_key;
}
}
return $return;
}
function input($field, $value, $function) {
global $types; global $types;
$name = htmlspecialchars(bracket_escape($name)); $name = htmlspecialchars(bracket_escape($field["field"]));
echo "<td class='function'>"; echo "<td class='function'>";
if ($field["type"] == "enum") { if ($field["type"] == "enum") {
echo "&nbsp;<td>" . (isset($_GET["select"]) ? ' <label><input type="radio" name="fields[' . $name . ']" value="-1" checked="checked"><em>' . lang('original') . '</em></label>' : ""); echo "&nbsp;<td>" . (isset($_GET["select"]) ? ' <label><input type="radio" name="fields[' . $name . ']" value="-1" checked="checked"><em>' . lang('original') . '</em></label>' : "");
@ -284,11 +294,14 @@ function input($name, $field, $value, $function) {
echo ' <label><input type="radio" name="fields[' . $name . ']" value="' . (isset($_GET["default"]) ? (strlen($val) ? htmlspecialchars($val) : " ") : $i+1) . '"' . ($checked ? ' checked="checked"' : '') . '>' . htmlspecialchars($val) . '</label>'; echo ' <label><input type="radio" name="fields[' . $name . ']" value="' . (isset($_GET["default"]) ? (strlen($val) ? htmlspecialchars($val) : " ") : $i+1) . '"' . ($checked ? ' checked="checked"' : '') . '>' . htmlspecialchars($val) . '</label>';
} }
} else { } else {
$first = ($field["null"] || isset($_GET["default"])) + isset($_GET["select"]); $functions = adminer_edit_functions($field);
$first = array_search("", $functions);
$onchange = ($first ? ' onchange="var f = this.form[\'function[' . addcslashes($name, "\r\n'\\") . ']\']; if (' . $first . ' > f.selectedIndex) f.selectedIndex = ' . $first . ';"' : ''); $onchange = ($first ? ' onchange="var f = this.form[\'function[' . addcslashes($name, "\r\n'\\") . ']\']; if (' . $first . ' > f.selectedIndex) f.selectedIndex = ' . $first . ';"' : '');
$options = adminer_edit_functions($field); echo (count($functions) > 1 ? '<select name="function[' . $name . ']">' . optionlist($functions, $function) . '</select>' : "&nbsp;") . '<td>';
echo (count($options) > 1 || isset($_GET["select"]) ? '<select name="function[' . $name . ']">' . (isset($_GET["select"]) ? '<option value="orig">' . lang('original') : '') . optionlist($options, $function) . '</select>' : "&nbsp;") . '<td>'; $options = adminer_edit_input($_GET["edit"], $field); // usage in call is without a table
if ($field["type"] == "set") { //! 64 bits if (is_array($options)) {
echo '<select name="fields[' . $name . ']"' . $onchange . '>' . optionlist($options, $value, true) . '</select>';
} elseif ($field["type"] == "set") { //! 64 bits
preg_match_all("~'((?:[^']+|'')*)'~", $field["length"], $matches); preg_match_all("~'((?:[^']+|'')*)'~", $field["length"], $matches);
foreach ($matches[1] as $i => $val) { foreach ($matches[1] as $i => $val) {
$val = stripcslashes(str_replace("''", "'", $val)); $val = stripcslashes(str_replace("''", "'", $val));
@ -302,7 +315,7 @@ function input($name, $field, $value, $function) {
} else { } else {
// int(3) is only a display hint // int(3) is only a display hint
$maxlength = (!ereg('int', $field["type"]) && preg_match('~^([0-9]+)(,([0-9]+))?$~', $field["length"], $match) ? ($match[1] + ($match[3] ? 1 : 0) + ($match[2] && !$field["unsigned"] ? 1 : 0)) : ($types[$field["type"]] ? $types[$field["type"]] + ($field["unsigned"] ? 0 : 1) : 0)); $maxlength = (!ereg('int', $field["type"]) && preg_match('~^([0-9]+)(,([0-9]+))?$~', $field["length"], $match) ? ($match[1] + ($match[3] ? 1 : 0) + ($match[2] && !$field["unsigned"] ? 1 : 0)) : ($types[$field["type"]] ? $types[$field["type"]] + ($field["unsigned"] ? 0 : 1) : 0));
echo '<input name="fields[' . $name . ']" value="' . htmlspecialchars($value) . '"' . ($maxlength ? " maxlength='$maxlength'" : "") . $onchange . '>'; echo '<input name="fields[' . $name . ']" value="' . htmlspecialchars($value) . '"' . ($maxlength ? " maxlength='$maxlength'" : "") . "$onchange>";
} }
} }
} }

View file

@ -20,7 +20,7 @@ unset($text_length);
foreach ($fields as $key => $field) { foreach ($fields as $key => $field) {
$name = adminer_field_name($fields, $key); $name = adminer_field_name($fields, $key);
if (isset($field["privileges"]["select"]) && strlen($name)) { if (isset($field["privileges"]["select"]) && strlen($name)) {
$columns[$key] = html_entity_decode(strip_tags($name)); //! numeric $key is problematic in optionlist() $columns[$key] = html_entity_decode(strip_tags($name));
if (ereg('text|blob', $field["type"])) { if (ereg('text|blob', $field["type"])) {
$text_length = (isset($_GET["text_length"]) ? $_GET["text_length"] : "100"); $text_length = (isset($_GET["text_length"]) ? $_GET["text_length"] : "100");
} }
@ -196,11 +196,11 @@ if (!$columns) {
foreach ($select as $key => $val) { foreach ($select as $key => $val) {
$val = $_GET["columns"][$key]; $val = $_GET["columns"][$key];
echo "<div><select name='columns[$i][fun]'><option>" . optionlist($fun_group, $val["fun"]) . "</select>"; echo "<div><select name='columns[$i][fun]'><option>" . optionlist($fun_group, $val["fun"]) . "</select>";
echo "<select name='columns[$i][col]'><option>" . optionlist($columns, $val["col"]) . "</select></div>\n"; echo "<select name='columns[$i][col]'><option>" . optionlist($columns, $val["col"], true) . "</select></div>\n";
$i++; $i++;
} }
echo "<div><select name='columns[$i][fun]' onchange='this.nextSibling.onchange();'><option>" . optionlist($fun_group) . "</select>"; echo "<div><select name='columns[$i][fun]' onchange='this.nextSibling.onchange();'><option>" . optionlist($fun_group) . "</select>";
echo "<select name='columns[$i][col]' onchange='select_add_row(this);'><option>" . optionlist($columns) . "</select></div>\n"; echo "<select name='columns[$i][col]' onchange='select_add_row(this);'><option>" . optionlist($columns, null, true) . "</select></div>\n";
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
echo '<fieldset><legend><a href="#fieldset-search" onclick="return !toggle(\'fieldset-search\');">' . lang('Search') . "</a></legend><div id='fieldset-search'" . ($where ? "" : " class='hidden'") . ">\n"; echo '<fieldset><legend><a href="#fieldset-search" onclick="return !toggle(\'fieldset-search\');">' . lang('Search') . "</a></legend><div id='fieldset-search'" . ($where ? "" : " class='hidden'") . ">\n";
@ -215,13 +215,13 @@ if (!$columns) {
$i = 0; $i = 0;
foreach ((array) $_GET["where"] as $val) { foreach ((array) $_GET["where"] as $val) {
if (strlen("$val[col]$val[val]") && in_array($val["op"], $operators)) { if (strlen("$val[col]$val[val]") && in_array($val["op"], $operators)) {
echo "<div><select name='where[$i][col]'><option value=''>" . lang('(anywhere)') . optionlist($columns, $val["col"]) . "</select>"; echo "<div><select name='where[$i][col]'><option value=''>" . lang('(anywhere)') . optionlist($columns, $val["col"], true) . "</select>";
echo "<select name='where[$i][op]'>" . optionlist($operators, $val["op"]) . "</select>"; echo "<select name='where[$i][op]'>" . optionlist($operators, $val["op"]) . "</select>";
echo "<input name='where[$i][val]' value=\"" . htmlspecialchars($val["val"]) . "\"></div>\n"; echo "<input name='where[$i][val]' value=\"" . htmlspecialchars($val["val"]) . "\"></div>\n";
$i++; $i++;
} }
} }
echo "<div><select name='where[$i][col]' onchange='select_add_row(this);'><option value=''>" . lang('(anywhere)') . optionlist($columns) . "</select>"; echo "<div><select name='where[$i][col]' onchange='select_add_row(this);'><option value=''>" . lang('(anywhere)') . optionlist($columns, null, true) . "</select>";
echo "<select name='where[$i][op]'>" . optionlist($operators) . "</select>"; echo "<select name='where[$i][op]'>" . optionlist($operators) . "</select>";
echo "<input name='where[$i][val]'></div>\n"; echo "<input name='where[$i][val]'></div>\n";
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
@ -230,12 +230,12 @@ if (!$columns) {
$i = 0; $i = 0;
foreach ((array) $_GET["order"] as $key => $val) { foreach ((array) $_GET["order"] as $key => $val) {
if (isset($columns[$val])) { if (isset($columns[$val])) {
echo "<div><select name='order[$i]'><option>" . optionlist($columns, $val) . "</select>"; echo "<div><select name='order[$i]'><option>" . optionlist($columns, $val, true) . "</select>";
echo "<label><input type='checkbox' name='desc[$i]' value='1'" . (isset($_GET["desc"][$key]) ? " checked='checked'" : "") . ">" . lang('descending') . "</label></div>\n"; echo "<label><input type='checkbox' name='desc[$i]' value='1'" . (isset($_GET["desc"][$key]) ? " checked='checked'" : "") . ">" . lang('descending') . "</label></div>\n";
$i++; $i++;
} }
} }
echo "<div><select name='order[$i]' onchange='select_add_row(this);'><option>" . optionlist($columns) . "</select>"; echo "<div><select name='order[$i]' onchange='select_add_row(this);'><option>" . optionlist($columns, null, true) . "</select>";
echo "<label><input type='checkbox' name='desc[$i]' value='1'>" . lang('descending') . "</label></div>\n"; echo "<label><input type='checkbox' name='desc[$i]' value='1'>" . lang('descending') . "</label></div>\n";
echo "</div></fieldset>\n"; echo "</div></fieldset>\n";
@ -277,12 +277,7 @@ if (!$columns) {
: count($rows) : count($rows)
); );
$foreign_keys = array(); $foreign_keys = column_foreign_keys($_GET["select"]);
foreach (foreign_keys($_GET["select"]) as $foreign_key) {
foreach ($foreign_key["source"] as $val) {
$foreign_keys[$val][] = $foreign_key;
}
}
$descriptions = adminer_row_descriptions($rows, $foreign_keys); $descriptions = adminer_row_descriptions($rows, $foreign_keys);
$backward_keys = adminer_backward_keys($_GET["select"]); $backward_keys = adminer_backward_keys($_GET["select"]);

View file

@ -2,7 +2,7 @@ Adminer 2.0.0:
Editor: User friendly data editor Editor: User friendly data editor
Customization: Adminer class Customization: Adminer class
E-mail sending E-mail sending
Table relations Table relations (Editor)
Create single column foreign key in table structure Create single column foreign key in table structure
Separate types to groups in table creation Separate types to groups in table creation
Show type in field name title (thanks to Jakub Sochor) Show type in field name title (thanks to Jakub Sochor)

View file

@ -62,6 +62,18 @@ function adminer_select_query($query) {
return call_adminer('select_query', "<!-- " . str_replace("--", "--><!--", $query) . " -->\n", $query); return call_adminer('select_query', "<!-- " . str_replace("--", "--><!--", $query) . " -->\n", $query);
} }
function adminer_row_description($table) {
$return = "";
// first varchar column
foreach (fields($table) as $field) {
if ($field["type"] == "varchar") {
$return = idf_escape($field["field"]);
break;
}
}
return call_adminer('row_description', $return, $table);
}
function adminer_row_descriptions($rows, $foreign_keys) { function adminer_row_descriptions($rows, $foreign_keys) {
global $dbh; global $dbh;
$return = $rows; $return = $rows;
@ -69,31 +81,26 @@ function adminer_row_descriptions($rows, $foreign_keys) {
foreach ((array) $foreign_keys[$key] as $foreign_key) { foreach ((array) $foreign_keys[$key] as $foreign_key) {
if (count($foreign_key["source"]) == 1) { if (count($foreign_key["source"]) == 1) {
$id = idf_escape($foreign_key["target"][0]); $id = idf_escape($foreign_key["target"][0]);
// find out the description column - first varchar $name = adminer_row_description($foreign_key["table"]);
$name = $id; if (strlen($name)) {
foreach (fields($foreign_key["table"]) as $field) { // find all used ids
if ($field["type"] == "varchar") { $ids = array();
$name = idf_escape($field["field"]); foreach ($rows as $row) {
break; $ids[$row[$key]] = $dbh->quote($row[$key]);
} }
// uses constant number of queries to get the descriptions, join would be complex, multiple queries would be slow
$descriptions = array();
$result = $dbh->query("SELECT $id, $name FROM " . idf_escape($foreign_key["table"]) . " WHERE $id IN (" . implode(", ", $ids) . ")");
while ($row = $result->fetch_row()) {
$descriptions[$row[0]] = $row[1];
}
$result->free();
// use the descriptions
foreach ($rows as $n => $row) {
$return[$n][$key] = $descriptions[$row[$key]];
}
break;
} }
// find all used ids
$ids = array();
foreach ($rows as $row) {
$ids[$row[$key]] = $dbh->quote($row[$key]);
}
// uses constant number of queries to get the descriptions, join would be complex, multiple queries would be slow
$descriptions = array();
$result = $dbh->query("SELECT $id, $name FROM " . idf_escape($foreign_key["table"]) . " WHERE $id IN (" . implode(", ", $ids) . ")");
while ($row = $result->fetch_row()) {
$descriptions[$row[0]] = $row[1];
}
$result->free();
// use the descriptions
foreach ($rows as $n => $row) {
$return[$n][$key] = $descriptions[$row[$key]];
}
break;
} }
} }
} }
@ -108,11 +115,35 @@ function adminer_select_val($val, $link) {
} }
function adminer_message_query($query) { function adminer_message_query($query) {
return call_adminer('message_query', "<!-- " . str_replace("--", "--><!--", $query) . " -->", $query); return call_adminer('message_query', "<!--\n" . str_replace("--", "--><!--", $query) . "\n-->", $query);
} }
function adminer_edit_functions($field) { function adminer_edit_functions($field) {
return call_adminer('edit_functions', array(""), $field); return call_adminer('edit_functions', (isset($_GET["select"]) ? array("orig" => lang('original')) : array()) + array(""), $field);
}
function adminer_edit_input($table, $field) {
global $dbh;
$return = null;
$foreign_keys = column_foreign_keys($table);
foreach ((array) $foreign_keys[$field["field"]] as $foreign_key) {
if (count($foreign_key["source"]) == 1) {
$id = idf_escape($foreign_key["target"][0]);
$name = adminer_row_description($foreign_key["table"]);
if (strlen($name) && $dbh->result($dbh->query("SELECT COUNT(*) FROM " . idf_escape($foreign_key["table"]))) <= 1000) { // optionlist with more than 1000 options would be too big
if ($field["null"]) {
$return[""] = "";
}
$result = $dbh->query("SELECT $id, $name FROM " . idf_escape($foreign_key["table"]) . " ORDER BY 2");
while ($row = $result->fetch_row()) {
$return[$row[0]] = $row[1];
}
$result->free();
break;
}
}
}
return call_adminer('edit_input', $return, $table, $field);
} }
function adminer_navigation($missing) { function adminer_navigation($missing) {