Skip to content

Commit

Permalink
Select from foreign keys in Editor
Browse files Browse the repository at this point in the history
git-svn-id: https://adminer.svn.sourceforge.net/svnroot/adminer/trunk@883 7c3ca157-0c34-0410-bff1-cbf682f78f5c
  • Loading branch information
jakubvrana committed Jul 23, 2009
1 parent f13efa8 commit 1e4d11e
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 53 deletions.
2 changes: 1 addition & 1 deletion adminer/call.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
if (strlen($value) && ($field["type"] == "enum" || $field["type"] == "set")) {
$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 "</table>\n";
Expand Down
2 changes: 1 addition & 1 deletion adminer/edit.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
: ($_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'))));
input($name, $field, $value, $function);
input($field, $value, $function);
if (isset($_GET["default"]) && $field["type"] == "timestamp") {
if (!isset($create) && !$_POST) {
//! disable sql_mode NO_FIELD_OPTIONS
Expand Down
23 changes: 20 additions & 3 deletions adminer/include/adminer.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/** 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 foreign keys
* @param array
* @return array
*/
function adminer_row_descriptions($rows, $foreign_keys) {
Expand Down Expand Up @@ -147,7 +155,16 @@ function adminer_edit_functions($field) {
if ($field["null"] || isset($_GET["default"])) {
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
Expand Down
31 changes: 22 additions & 9 deletions adminer/include/functions.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ function bracket_escape($idf, $back = false) {
return strtr($idf, ($back ? array_flip($trans) : $trans));
}

function optionlist($options, $selected = null) {
function optionlist($options, $selected = null, $use_keys = false) {
$return = "";
foreach ($options as $k => $v) {
if (is_array($v)) {
$return .= '<optgroup label="' . htmlspecialchars($k) . '">';
}
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)) {
$return .= '</optgroup>';
Expand Down Expand Up @@ -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;
$name = htmlspecialchars(bracket_escape($name));
$name = htmlspecialchars(bracket_escape($field["field"]));
echo "<td class='function'>";
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>' : "");
Expand All @@ -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>';
}
} 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 . ';"' : '');
$options = adminer_edit_functions($field);
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>';
if ($field["type"] == "set") { //! 64 bits
echo (count($functions) > 1 ? '<select name="function[' . $name . ']">' . optionlist($functions, $function) . '</select>' : "&nbsp;") . '<td>';
$options = adminer_edit_input($_GET["edit"], $field); // usage in call is without a table
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);
foreach ($matches[1] as $i => $val) {
$val = stripcslashes(str_replace("''", "'", $val));
Expand All @@ -302,7 +315,7 @@ function input($name, $field, $value, $function) {
} else {
// 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));
echo '<input name="fields[' . $name . ']" value="' . htmlspecialchars($value) . '"' . ($maxlength ? " maxlength='$maxlength'" : "") . $onchange . '>';
echo '<input name="fields[' . $name . ']" value="' . htmlspecialchars($value) . '"' . ($maxlength ? " maxlength='$maxlength'" : "") . "$onchange>";
}
}
}
Expand Down
21 changes: 8 additions & 13 deletions adminer/select.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
foreach ($fields as $key => $field) {
$name = adminer_field_name($fields, $key);
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"])) {
$text_length = (isset($_GET["text_length"]) ? $_GET["text_length"] : "100");
}
Expand Down Expand Up @@ -196,11 +196,11 @@
foreach ($select as $key => $val) {
$val = $_GET["columns"][$key];
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++;
}
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 '<fieldset><legend><a href="#fieldset-search" onclick="return !toggle(\'fieldset-search\');">' . lang('Search') . "</a></legend><div id='fieldset-search'" . ($where ? "" : " class='hidden'") . ">\n";
Expand All @@ -215,13 +215,13 @@
$i = 0;
foreach ((array) $_GET["where"] as $val) {
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 "<input name='where[$i][val]' value=\"" . htmlspecialchars($val["val"]) . "\"></div>\n";
$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 "<input name='where[$i][val]'></div>\n";
echo "</div></fieldset>\n";
Expand All @@ -230,12 +230,12 @@
$i = 0;
foreach ((array) $_GET["order"] as $key => $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";
$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 "</div></fieldset>\n";

Expand Down Expand Up @@ -277,12 +277,7 @@
: count($rows)
);

$foreign_keys = array();
foreach (foreign_keys($_GET["select"]) as $foreign_key) {
foreach ($foreign_key["source"] as $val) {
$foreign_keys[$val][] = $foreign_key;
}
}
$foreign_keys = column_foreign_keys($_GET["select"]);
$descriptions = adminer_row_descriptions($rows, $foreign_keys);

$backward_keys = adminer_backward_keys($_GET["select"]);
Expand Down
2 changes: 1 addition & 1 deletion changes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Adminer 2.0.0:
Editor: User friendly data editor
Customization: Adminer class
E-mail sending
Table relations
Table relations (Editor)
Create single column foreign key in table structure
Separate types to groups in table creation
Show type in field name title (thanks to Jakub Sochor)
Expand Down
81 changes: 56 additions & 25 deletions editor/include/adminer.inc.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,38 +62,45 @@ function adminer_select_query($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) {
global $dbh;
$return = $rows;
foreach ($rows[0] as $key => $val) {
foreach ((array) $foreign_keys[$key] as $foreign_key) {
if (count($foreign_key["source"]) == 1) {
$id = idf_escape($foreign_key["target"][0]);
// find out the description column - first varchar
$name = $id;
foreach (fields($foreign_key["table"]) as $field) {
if ($field["type"] == "varchar") {
$name = idf_escape($field["field"]);
break;
$name = adminer_row_description($foreign_key["table"]);
if (strlen($name)) {
// 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;
}
// 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;
}
}
}
Expand All @@ -108,11 +115,35 @@ function adminer_select_val($val, $link) {
}

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) {
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) {
Expand Down

0 comments on commit 1e4d11e

Please sign in to comment.