1
0
mirror of https://github.com/vrana/adminer.git synced 2025-09-02 02:42:37 +02:00

Compare commits

...

35 Commits

Author SHA1 Message Date
Jakub Vrana
2d18afaf7f Release 3.5.1 2012-08-09 22:47:12 -07:00
Jakub Vrana
9a3b3db4f6 Comment 2012-08-09 12:18:31 -07:00
Jakub Vrana
a4e38a266d Remove definer from routine and event 2012-08-09 09:39:12 -07:00
Jakub Vrana
ca32e71e42 Ignore bit type when searching strings 2012-08-09 09:37:51 -07:00
Jakub Vrana
4b4fa16a37 Autodisplay long table names in tables filter plugin 2012-08-09 09:11:55 -07:00
Jakub Vrana
69d49e30c5 Support same name fields in CSV export 2012-08-09 08:57:45 -07:00
Jakub Vrana
7fcfb0d16a Don't include trailing space to delimiter 2012-08-09 08:39:54 -07:00
Jakub Vrana
1501d60f14 Descending order after second click on column caption 2012-08-08 22:40:38 -07:00
Jakub Vrana
e5b1c99d87 Support Shift+click in export 2012-08-08 09:23:46 -07:00
Jakub Vrana
b49061b863 Add JS function for getting parent tag 2012-08-08 09:22:23 -07:00
Jakub Vrana
5fd21e122a Set source checkbox only in click without Shift 2012-08-08 08:54:15 -07:00
Jakub Vrana
b783b9487d Don't display tables list on server pages 2012-08-08 08:41:52 -07:00
Jakub Vrana
99343701ab Autodisplay long logins in saved logins list 2012-08-08 08:27:50 -07:00
Jakub Vrana
c09a147b2e Develop 2012-08-05 09:15:05 -07:00
Jakub Vrana
a0af3eec5c Release 3.5.0 2012-08-04 22:53:20 -07:00
Jakub Vrana
1dd6dbcce2 Support one click search in Editor 2012-08-04 22:52:50 -07:00
Jakub Vrana
95f0a5f0f0 Fix test 2012-08-04 22:34:38 -07:00
Jakub Vrana
335ab7eab2 Done 2012-07-30 00:57:24 -07:00
Jakub Vrana
6a486181dd Autodisplay long table names in tables list 2012-07-29 16:05:37 -07:00
Jakub Vrana
57e5896b55 Autohide column context menu in select 2012-07-29 13:55:39 -07:00
Jakub Vrana
ac668d1331 Treat queries with no limit as full table scans 2012-07-29 13:28:04 -07:00
Jakub Vrana
55831095b6 Warn about grouping data without index 2012-07-29 13:25:59 -07:00
Jakub Vrana
07e2c3b2a4 Save bytes 2012-07-29 11:29:21 -07:00
Jakub Vrana
e2dbb9c7bd Links for column search in select 2012-07-29 11:29:00 -07:00
Jakub Vrana
e8b95f127f SQLite: Display number of rows in database overview 2012-07-29 10:45:38 -07:00
Jakub Vrana
f1153aa35a Display assigned auto_increment after clone 2012-07-27 17:37:20 -07:00
Jakub Vrana
5e4b815893 Highlight also killed queries 2012-07-27 16:08:09 -07:00
Jakub Vrana
a227ec1c97 Don't treat enum in PostgreSQL as special (bug #3545899) 2012-07-21 09:50:50 -07:00
Jakub Vrana
98483e101d SQLite: Better editing in tables without a primary key 2012-07-15 14:55:46 -07:00
Jakub Vrana
c2f95e0054 SQLite: Full alter table 2012-07-15 14:38:45 -07:00
Jakub Vrana
5fb2368b66 Ignore SQLite autoindexes 2012-07-15 12:24:20 -07:00
Jakub Vrana
385fdd45b8 Document trigger type 2012-07-15 12:04:04 -07:00
Jakub Vrana
56cd77f0d1 Save bytes 2012-07-15 10:05:13 -07:00
Jakub Vrana
7291ae608d Reset error before using in SQL query 2012-07-15 09:21:22 -07:00
Jakub Vrana
6a3cf71db5 Develop 2012-06-30 05:26:22 -07:00
26 changed files with 354 additions and 132 deletions

View File

@@ -23,10 +23,12 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"] && !$_POST["up"]
query_redirect("DROP TABLE " . table($TABLE), substr(ME, 0, -1), lang('Table has been dropped.'));
} else {
$fields = array();
$all_fields = array();
$use_all_fields = false;
$foreign = array();
ksort($_POST["fields"]);
$orig_field = reset($orig_fields);
$after = "FIRST";
$after = " FIRST";
foreach ($_POST["fields"] as $key => $field) {
$foreign_key = $foreign_keys[$field["type"]];
$type_field = ($foreign_key !== null ? $referencable_primary[$foreign_key] : $field); //! can collide with user defined type
@@ -43,18 +45,26 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"] && !$_POST["up"]
$field["auto_increment"] = true;
}
$process_field = process_field($field, $type_field);
$all_fields[] = array($field["orig"], $process_field, $after);
if ($process_field != process_field($orig_field, $orig_field)) {
$fields[] = array($field["orig"], $process_field, $after);
if ($field["orig"] != "" || $after) {
$use_all_fields = true;
}
}
if ($foreign_key !== null) {
$foreign[idf_escape($field["field"])] = ($TABLE != "" ? "ADD" : " ") . " FOREIGN KEY (" . idf_escape($field["field"]) . ") REFERENCES " . table($foreign_keys[$field["type"]]) . " (" . idf_escape($type_field["field"]) . ")" . (ereg("^($on_actions)\$", $field["on_delete"]) ? " ON DELETE $field[on_delete]" : "");
$foreign[idf_escape($field["field"])] = ($TABLE != "" && $jush != "sqlite" ? "ADD" : " ") . " FOREIGN KEY (" . idf_escape($field["field"]) . ") REFERENCES " . table($foreign_keys[$field["type"]]) . " (" . idf_escape($type_field["field"]) . ")" . (ereg("^($on_actions)\$", $field["on_delete"]) ? " ON DELETE $field[on_delete]" : "");
}
$after = "AFTER " . idf_escape($field["field"]);
$after = " AFTER " . idf_escape($field["field"]);
} elseif ($field["orig"] != "") {
$use_all_fields = true;
$fields[] = array($field["orig"]);
}
if ($field["orig"] != "") {
$orig_field = next($orig_fields);
if (!$orig_field) {
$after = "";
}
}
}
$partitioning = "";
@@ -82,7 +92,7 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"] && !$_POST["up"]
queries_redirect(ME . "table=" . urlencode($name), $message, alter_table(
$TABLE,
$name,
$fields,
($jush == "sqlite" && ($use_all_fields || $foreign) ? $all_fields : $fields),
$foreign,
$_POST["Comment"],
($_POST["Engine"] && $_POST["Engine"] != $orig_status["Engine"] ? $_POST["Engine"] : ""),

View File

@@ -43,6 +43,7 @@ if (isset($_GET["mssql"])) {
function query($query, $unbuffered = false) {
$result = sqlsrv_query($this->_link, $query); //! , array(), ($unbuffered ? array() : array("Scrollable" => "keyset"))
$this->error = "";
if (!$result) {
$this->_get_error();
return false;
@@ -52,6 +53,7 @@ if (isset($_GET["mssql"])) {
function multi_query($query) {
$this->_result = sqlsrv_query($this->_link, $query);
$this->error = "";
if (!$this->_result) {
$this->_get_error();
return false;
@@ -159,6 +161,7 @@ if (isset($_GET["mssql"])) {
function query($query, $unbuffered = false) {
$result = mssql_query($query, $this->_link); //! $unbuffered
$this->error = "";
if (!$result) {
$this->error = mssql_get_last_message();
return false;

View File

@@ -108,6 +108,7 @@ if (!defined("DRIVER")) {
*/
function query($query, $unbuffered = false) {
$result = @($unbuffered ? mysql_unbuffered_query($query, $this->_link) : mysql_query($query, $this->_link)); // @ - mute mysql.trace_mode
$this->error = "";
if (!$result) {
$this->error = mysql_error($this->_link);
return false;
@@ -602,7 +603,7 @@ if (!defined("DRIVER")) {
$alter = array();
foreach ($fields as $field) {
$alter[] = ($field[1]
? ($table != "" ? ($field[0] != "" ? "CHANGE " . idf_escape($field[0]) : "ADD") : " ") . " " . implode($field[1]) . ($table != "" ? " $field[2]" : "")
? ($table != "" ? ($field[0] != "" ? "CHANGE " . idf_escape($field[0]) : "ADD") : " ") . " " . implode($field[1]) . ($table != "" ? $field[2] : "")
: "DROP " . idf_escape($field[0])
);
}
@@ -708,7 +709,7 @@ if (!defined("DRIVER")) {
/** Get information about trigger
* @param string trigger name
* @return array array("Trigger" => , "Timing" => , "Event" => , "Statement" => )
* @return array array("Trigger" => , "Timing" => , "Event" => , "Type" => , "Statement" => )
*/
function trigger($name) {
if ($name == "") {

View File

@@ -37,6 +37,7 @@ if (isset($_GET["oracle"])) {
function query($query, $unbuffered = false) {
$result = oci_parse($this->_link, $query);
$this->error = "";
if (!$result) {
$error = oci_error($this->_link);
$this->error = $error["message"];

View File

@@ -58,6 +58,7 @@ if (isset($_GET["pgsql"])) {
function query($query, $unbuffered = false) {
$result = @pg_query($this->_link, $query);
$this->error = "";
if (!$result) {
$this->error = pg_last_error($this->_link);
return false;

View File

@@ -19,6 +19,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
function query($query) {
$result = @$this->_link->query($query);
$this->error = "";
if (!$result) {
$this->error = $this->_link->lastErrorMsg();
return false;
@@ -93,6 +94,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
function query($query, $unbuffered = false) {
$method = ($unbuffered ? "unbufferedQuery" : "query");
$result = @$this->_link->$method($query, SQLITE_BOTH, $error);
$this->error = "";
if (!$result) {
$this->error = $error;
return false;
@@ -248,9 +250,12 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
}
function table_status($name = "") {
global $connection;
$return = array();
foreach (get_rows("SELECT name AS Name, type AS Engine FROM sqlite_master WHERE type IN ('table', 'view')" . ($name != "" ? " AND name = " . q($name) : "")) as $row) {
$row["Oid"] = "t";
$row["Auto_increment"] = "";
$row["Rows"] = $connection->result("SELECT COUNT(*) FROM " . idf_escape($row["Name"]));
$return[$row["Name"]] = $row;
}
foreach (get_rows("SELECT * FROM sqlite_sequence", null, "") as $row) {
@@ -265,7 +270,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
function fk_support($table_status) {
global $connection;
return $_GET["create"] == "" && !$connection->result("SELECT sqlite_compileoption_used('OMIT_FOREIGN_KEY')");
return !$connection->result("SELECT sqlite_compileoption_used('OMIT_FOREIGN_KEY')");
}
function fields($table) {
@@ -299,10 +304,12 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
$return[""] = array("type" => "PRIMARY", "columns" => $primary, "lengths" => array());
}
foreach (get_rows("PRAGMA index_list(" . table($table) . ")") as $row) {
$return[$row["name"]]["type"] = ($row["unique"] ? "UNIQUE" : "INDEX");
$return[$row["name"]]["lengths"] = array();
foreach (get_rows("PRAGMA index_info(" . idf_escape($row["name"]) . ")") as $row1) {
$return[$row["name"]]["columns"][] = $row1["name"];
if (!ereg("^sqlite_", $row["name"])) {
$return[$row["name"]]["type"] = ($row["unique"] ? "UNIQUE" : "INDEX");
$return[$row["name"]]["lengths"] = array();
foreach (get_rows("PRAGMA index_info(" . idf_escape($row["name"]) . ")") as $row1) {
$return[$row["name"]]["columns"][] = $row1["name"];
}
}
}
return $return;
@@ -398,14 +405,90 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
}
function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
$alter = array();
$use_all_fields = ($table == "" || $foreign);
foreach ($fields as $field) {
if ($field[1]) {
$alter[] = ($table != "" && $field[0] == "" ? "ADD " : " ") . implode($field[1]);
if ($field[0] != "" || !$field[1] || $field[2]) {
$use_all_fields = true;
break;
}
}
$alter = array_merge($alter, $foreign);
if ($table != "") {
$alter = array();
$originals = array();
$primary_key = false;
foreach ($fields as $field) {
if ($field[1]) {
if ($field[1][6]) {
$primary_key = true;
}
$alter[] = ($use_all_fields ? " " : "ADD ") . implode($field[1]);
if ($field[0] != "") {
$originals[$field[0]] = $field[1][0];
}
}
}
if ($use_all_fields) {
if ($table != "") {
queries("BEGIN");
foreach (foreign_keys($table) as $foreign_key) {
$columns = array();
foreach ($foreign_key["source"] as $column) {
if (!$originals[$column]) {
continue 2;
}
$columns[] = $originals[$column];
}
$foreign[] = " FOREIGN KEY (" . implode(", ", $columns) . ") REFERENCES "
. table($foreign_key["table"])
. " (" . implode(", ", array_map('idf_escape', $foreign_key["target"]))
. ") ON DELETE $foreign_key[on_delete] ON UPDATE $foreign_key[on_update]"
;
}
$indexes = array();
foreach (indexes($table) as $key_name => $index) {
$columns = array();
foreach ($index["columns"] as $column) {
if (!$originals[$column]) {
continue 2;
}
$columns[] = $originals[$column];
}
$columns = "(" . implode(", ", $columns) . ")";
if ($index["type"] != "PRIMARY") {
$indexes[] = array($index["type"], $key_name, $columns);
} elseif (!$primary_key) {
$foreign[] = " PRIMARY KEY $columns";
}
}
}
$alter = array_merge($alter, $foreign);
if (!queries("CREATE TABLE " . table($table != "" ? "adminer_$name" : $name) . " (\n" . implode(",\n", $alter) . "\n)")) {
// implicit ROLLBACK to not overwrite $connection->error
return false;
}
if ($table != "") {
if ($originals && !queries("INSERT INTO " . table("adminer_$name") . " (" . implode(", ", $originals) . ") SELECT " . implode(", ", array_map('idf_escape', array_keys($originals))) . " FROM " . table($table))) {
return false;
}
$triggers = array();
foreach (triggers($table) as $trigger_name => $timing_event) {
$trigger = trigger($trigger_name);
$triggers[] = "CREATE TRIGGER " . idf_escape($trigger_name) . " " . implode(" ", $timing_event) . " ON " . table($name) . "\n$trigger[Statement]";
}
if (!queries("DROP TABLE " . table($table))) { // drop before creating indexes and triggers to allow using old names
return false;
}
queries("ALTER TABLE " . table("adminer_$name") . " RENAME TO " . table($name));
if (!alter_indexes($name, $indexes)) {
return false;
}
foreach ($triggers as $trigger) {
if (!queries($trigger)) {
return false;
}
}
queries("COMMIT");
}
} else {
foreach ($alter as $val) {
if (!queries("ALTER TABLE " . table($table) . " $val")) {
return false;
@@ -414,8 +497,6 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
if ($table != $name && !queries("ALTER TABLE " . table($table) . " RENAME TO " . table($name))) {
return false;
}
} elseif (!queries("CREATE TABLE " . table($name) . " (\n" . implode(",\n", $alter) . "\n)")) {
return false;
}
if ($auto_increment) {
queries("UPDATE sqlite_sequence SET seq = $auto_increment WHERE name = " . q($name)); // ignores error
@@ -563,7 +644,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
}
function support($feature) {
return ereg('^(view|trigger|variables|status|dump)$', $feature);
return ereg('^(view|trigger|variables|status|dump|move_col|drop_col)$', $feature);
}
$jush = "sqlite";

View File

@@ -48,14 +48,14 @@ SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
foreach (array("FUNCTION", "PROCEDURE") as $routine) {
foreach (get_rows("SHOW $routine STATUS WHERE Db = " . q($db), null, "-- ") as $row) {
$out .= ($style != 'DROP+CREATE' ? "DROP $routine IF EXISTS " . idf_escape($row["Name"]) . ";;\n" : "")
. $connection->result("SHOW CREATE $routine " . idf_escape($row["Name"]), 2) . ";;\n\n";
. remove_definer($connection->result("SHOW CREATE $routine " . idf_escape($row["Name"]), 2)) . ";;\n\n";
}
}
}
if ($_POST["events"]) {
foreach (get_rows("SHOW EVENTS", null, "-- ") as $row) {
$out .= ($style != 'DROP+CREATE' ? "DROP EVENT IF EXISTS " . idf_escape($row["Name"]) . ";;\n" : "")
. $connection->result("SHOW CREATE EVENT " . idf_escape($row["Name"]), 3) . ";;\n\n";
. remove_definer($connection->result("SHOW CREATE EVENT " . idf_escape($row["Name"]), 3)) . ";;\n\n";
}
}
if ($out) {
@@ -197,11 +197,11 @@ if (DB != "") {
$name = $table_status["Name"];
$prefix = ereg_replace("_.*", "", $name);
$checked = ($TABLE == "" || $TABLE == (substr($TABLE, -1) == "%" ? "$prefix%" : $name)); //! % may be part of table name
$print = "<tr><td>" . checkbox("tables[]", $name, $checked, $name, "formUncheck('check-tables');");
$print = "<tr><td>" . checkbox("tables[]", $name, $checked, $name, "checkboxClick(event, this); formUncheck('check-tables');");
if (is_view($table_status)) {
$views .= "$print\n";
} else {
echo "$print<td align='right'><label>" . ($table_status["Engine"] == "InnoDB" && $table_status["Rows"] ? "~ " : "") . $table_status["Rows"] . checkbox("data[]", $name, $checked, "", "formUncheck('check-data');") . "</label>\n";
echo "$print<td align='right'><label>" . ($table_status["Engine"] == "InnoDB" && $table_status["Rows"] ? "~ " : "") . $table_status["Rows"] . checkbox("data[]", $name, $checked, "", "checkboxClick(event, this); formUncheck('check-data');") . "</label>\n";
}
$prefixes[$prefix]++;
}

View File

@@ -53,7 +53,7 @@ if ($_POST["save"]) {
$select = array();
foreach ($fields as $name => $field) {
if (isset($field["privileges"]["select"])) {
$select[] = ($_POST["clone"] && $field["auto_increment"] ? "'' AS " : (ereg("enum|set", $field["type"]) ? "1*" . idf_escape($name) . " AS " : "")) . idf_escape($name);
$select[] = ($_POST["clone"] && $field["auto_increment"] ? "'' AS " : ($jush == "sql" && ereg("enum|set", $field["type"]) ? "1*" . idf_escape($name) . " AS " : "")) . idf_escape($name);
}
}
$row = array();
@@ -76,7 +76,7 @@ if ($fields) {
echo "<tr><th>" . $adminer->fieldName($field);
$default = $_GET["set"][bracket_escape($name)];
$value = ($row !== null
? ($row[$name] != "" && ereg("enum|set", $field["type"]) ? (is_array($row[$name]) ? array_sum($row[$name]) : +$row[$name]) : $row[$name])
? ($row[$name] != "" && $jush == "sql" && ereg("enum|set", $field["type"]) ? (is_array($row[$name]) ? array_sum($row[$name]) : +$row[$name]) : $row[$name])
: (!$update && $field["auto_increment"] ? "" : (isset($_GET["select"]) ? false : ($default !== null ? $default : $field["default"])))
);
if (!$_POST["save"] && is_string($value)) {

View File

@@ -214,7 +214,7 @@ username.form['auth[driver]'].onchange();
foreach ($select as $key => $val) {
$val = $_GET["columns"][$key];
echo "<div>" . html_select("columns[$i][fun]", array(-1 => "") + $fun_group, $val["fun"]);
echo "(<select name='columns[$i][col]'><option>" . optionlist($columns, $val["col"], true) . "</select>)</div>\n";
echo "(<select name='columns[$i][col]' onchange='selectFieldChange(this.form);'><option>" . optionlist($columns, $val["col"], true) . "</select>)</div>\n";
$i++;
}
echo "<div>" . html_select("columns[$i][fun]", array(-1 => "") + $fun_group, "", "this.nextSibling.nextSibling.onchange();");
@@ -279,7 +279,7 @@ username.form['auth[driver]'].onchange();
*/
function selectLimitPrint($limit) {
echo "<fieldset><legend>" . lang('Limit') . "</legend><div>"; // <div> for easy styling
echo "<input name='limit' size='3' value='" . h($limit) . "'>";
echo "<input name='limit' size='3' value='" . h($limit) . "' onchange='selectFieldChange(this.form);'>";
echo "</div></fieldset>\n";
}
@@ -395,7 +395,7 @@ username.form['auth[driver]'].onchange();
// find anywhere
$cols = array();
foreach ($fields as $name => $field) {
if (is_numeric($val["val"]) || !ereg('int|float|double|decimal', $field["type"])) {
if (is_numeric($val["val"]) || !ereg('int|float|double|decimal|bit', $field["type"])) {
$name = idf_escape($name);
$cols[] = ($jush == "sql" && ereg('char|text|enum|set', $field["type"]) && !ereg('^utf8', $field["collation"]) ? "CONVERT($name USING utf8)" : $name);
}
@@ -573,8 +573,7 @@ username.form['auth[driver]'].onchange();
echo "DROP " . ($is_view ? "VIEW" : "TABLE") . " IF EXISTS " . table($table) . ";\n";
}
if ($is_view) {
// remove DEFINER with current user
$create = preg_replace('~^([A-Z =]+) DEFINER=`' . preg_replace('~@(.*)~', '`@`(%|\\1)', logged_user()) . '`~', '\\1', $create); //! proper escaping of user
$create = remove_definer($create);
}
echo ($style != "CREATE+ALTER" ? $create : ($is_view ? substr_replace($create, " OR REPLACE", 6, 0) : substr_replace($create, " IF NOT EXISTS", 12, 0))) . ";\n\n";
}
@@ -672,25 +671,32 @@ DROP PROCEDURE adminer_alter;
if ($result) {
$insert = "";
$buffer = "";
while ($row = $result->fetch_assoc()) {
$keys = array();
while ($row = $result->fetch_row()) {
if (!$keys) {
foreach ($row as $val) {
$field = $result->fetch_field();
$keys[] = $field->name;
}
}
if ($_POST["format"] != "sql") {
if ($style == "table") {
dump_csv(array_keys($row));
dump_csv($keys);
$style = "INSERT";
}
dump_csv($row);
} else {
if (!$insert) {
$insert = "INSERT INTO " . table($table) . " (" . implode(", ", array_map('idf_escape', array_keys($row))) . ") VALUES";
$insert = "INSERT INTO " . table($table) . " (" . implode(", ", array_map('idf_escape', $keys)) . ") VALUES";
}
foreach ($row as $key => $val) {
$row[$key] = ($val !== null ? (ereg('int|float|double|decimal|bit', $fields[$key]["type"]) ? $val : q($val)) : "NULL"); //! columns looking like functions
$row[$key] = ($val !== null ? (ereg('int|float|double|decimal|bit', $fields[$keys[$key]]["type"]) ? $val : q($val)) : "NULL"); //! columns looking like functions
}
$s = implode(",\t", $row);
if ($style == "INSERT+UPDATE") {
$set = array();
foreach ($row as $key => $val) {
$set[] = idf_escape($key) . " = $val";
$set[] = idf_escape($keys[$key]) . " = $val";
}
echo "$insert ($s) ON DUPLICATE KEY UPDATE " . implode(", ", $set) . ";\n";
} else {
@@ -777,7 +783,7 @@ DROP PROCEDURE adminer_alter;
foreach ($usernames as $username => $password) {
if ($password !== null) {
if ($first) {
echo "<p>\n";
echo "<p id='logins' onmouseover='menuOver(this);' onmouseout='menuOut(this);'>\n";
$first = false;
}
echo "<a href='" . h(auth_url($driver, $server, $username)) . "'>($drivers[$driver]) " . h($username . ($server != "" ? "@$server" : "")) . "</a><br>\n";
@@ -803,7 +809,7 @@ DROP PROCEDURE adminer_alter;
</p>
</form>
<form action="">
<p>
<p id="dbs">
<?php hidden_fields_get(); ?>
<?php echo ($databases ? html_select("db", array("" => "(" . lang('database') . ")") + $databases, DB, "this.form.submit();") : '<input name="db" value="' . h(DB) . '">'); ?>
<input type="submit" value="<?php echo lang('Use'); ?>"<?php echo ($databases ? " class='hidden'" : ""); ?>>
@@ -815,31 +821,31 @@ DROP PROCEDURE adminer_alter;
set_schema($_GET["ns"]);
}
}
if ($_GET["ns"] !== "" && !$missing) {
echo '<p><a href="' . h(ME) . 'create="' . bold($_GET["create"] === "") . ">" . lang('Create new table') . "</a>\n";
$tables = tables_list();
if (!$tables) {
echo "<p class='message'>" . lang('No tables.') . "\n";
} else {
$this->tablesPrint($tables);
$links = array();
foreach ($tables as $table => $type) {
$links[] = preg_quote($table, '/');
}
echo "<script type='text/javascript'>\n";
echo "var jushLinks = { $jush: [ '" . js_escape(ME) . "table=\$&', /\\b(" . implode("|", $links) . ")\\b/g ] };\n";
foreach (array("bac", "bra", "sqlite_quo", "mssql_bra") as $val) {
echo "jushLinks.$val = jushLinks.$jush;\n";
}
echo "</script>\n";
}
}
}
echo (isset($_GET["sql"]) ? '<input type="hidden" name="sql" value="">'
: (isset($_GET["schema"]) ? '<input type="hidden" name="schema" value="">'
: (isset($_GET["dump"]) ? '<input type="hidden" name="dump" value="">'
: "")));
echo "</p></form>\n";
if ($_GET["ns"] !== "" && !$missing && DB != "") {
echo '<p><a href="' . h(ME) . 'create="' . bold($_GET["create"] === "") . ">" . lang('Create new table') . "</a>\n";
$tables = tables_list();
if (!$tables) {
echo "<p class='message'>" . lang('No tables.') . "\n";
} else {
$this->tablesPrint($tables);
$links = array();
foreach ($tables as $table => $type) {
$links[] = preg_quote($table, '/');
}
echo "<script type='text/javascript'>\n";
echo "var jushLinks = { $jush: [ '" . js_escape(ME) . "table=\$&', /\\b(" . implode("|", $links) . ")\\b/g ] };\n";
foreach (array("bac", "bra", "sqlite_quo", "mssql_bra") as $val) {
echo "jushLinks.$val = jushLinks.$jush;\n";
}
echo "</script>\n";
}
}
}
}
@@ -848,7 +854,7 @@ DROP PROCEDURE adminer_alter;
* @return null
*/
function tablesPrint($tables) {
echo "<p id='tables'>\n";
echo "<p id='tables' onmouseover='menuOver(this);' onmouseout='menuOut(this);'>\n";
foreach ($tables as $table => $type) {
echo '<a href="' . h(ME) . 'select=' . urlencode($table) . '"' . bold($_GET["select"] == $table) . ">" . lang('select') . "</a> ";
echo '<a href="' . h(ME) . 'table=' . urlencode($table) . '"' . bold($_GET["table"] == $table) . " title='" . lang('Show structure') . "'>" . $this->tableName(array("Name" => $table)) . "</a><br>\n"; //! Adminer::tableName may work with full table status

View File

@@ -357,6 +357,14 @@ function drop_create($drop, $create, $location, $message_drop, $message_alter, $
return $dropped;
}
/** Remove current user definer from SQL command
* @param string
* @return string
*/
function remove_definer($query) {
return preg_replace('~^([A-Z =]+) DEFINER=`' . preg_replace('~@(.*)~', '`@`(%|\\1)', logged_user()) . '`~', '\\1', $query); //! proper escaping of user
}
/** Get string to add a file in TAR
* @param string
* @param string

View File

@@ -24,6 +24,7 @@ if (extension_loaded('pdo')) {
function query($query, $unbuffered = false) {
$result = parent::query($query);
$this->error = "";
if (!$result) {
$errorInfo = $this->errorInfo();
$this->error = $errorInfo[2];

View File

@@ -1,2 +1,2 @@
<?php
$VERSION = "3.4.0";
$VERSION = "3.5.1";

View File

@@ -24,7 +24,7 @@ foreach (process_list() as $i => $row) {
echo "<tr" . odd() . ">" . (support("kill") ? "<td>" . checkbox("kill[]", $row["Id"], 0) : "");
foreach ($row as $key => $val) {
echo "<td>" . (
($jush == "sql" && $key == "Info" && $row["Command"] == "Query" && $val != "") ||
($jush == "sql" && $key == "Info" && ereg("Query|Killed", $row["Command"]) && $val != "") ||
($jush == "pgsql" && $key == "current_query" && $val != "<IDLE>") ||
($jush == "oracle" && $key == "sql_text" && $val != "")
? "<code class='jush-$jush'>" . shorten_utf8($val, 100, "</code>") . ' <a href="' . h(ME . ($row["db"] != "" ? "db=" . urlencode($row["db"]) . "&" : "") . "sql=" . urlencode($val)) . '">' . lang('Edit') . '</a>'

View File

@@ -13,10 +13,10 @@ if ($_GET["script"] == "db") {
foreach ($sums + array("Auto_increment" => 0, "Rows" => 0) as $key => $val) {
if ($table_status[$key] != "") {
$val = number_format($table_status[$key], 0, '.', lang(','));
json_row("$key-$id", ($key == "Rows" && $val && (
$table_status["Engine"] == "InnoDB" || // MySQL InnoDB
$table_status["Engine"] == "table" // PostgreSQL table reltype
) ? "~ $val" : $val));
json_row("$key-$id", ($key == "Rows" && $val && $table_status["Engine"] == ($sql == "pgsql" ? "table" : "InnoDB")
? "~ $val"
: $val
));
if (isset($sums[$key])) {
// ignore innodb_file_per_table because it is not active for tables created before it was enabled
$sums[$key] += ($table_status["Engine"] != "InnoDB" || $key != "Data_free" ? $table_status[$key] : 0);

View File

@@ -4,8 +4,10 @@ $table_status = table_status($TABLE);
$indexes = indexes($TABLE);
$fields = fields($TABLE);
$foreign_keys = column_foreign_keys($TABLE);
$oid = "";
if ($table_status["Oid"] == "t") {
$indexes[] = array("type" => "PRIMARY", "columns" => array("oid"));
$oid = ($jush == "sqlite" ? "rowid" : "oid");
$indexes[] = array("type" => "PRIMARY", "columns" => array($oid));
}
parse_str($_COOKIE["adminer_import"], $adminer_import);
@@ -27,7 +29,7 @@ list($select, $group) = $adminer->selectColumnsProcess($columns, $indexes);
$where = $adminer->selectSearchProcess($fields, $indexes);
$order = $adminer->selectOrderProcess($fields, $indexes);
$limit = $adminer->selectLimitProcess();
$from = ($select ? implode(", ", $select) : ($table_status["Oid"] == "t" ? "oid, " : "") . "*") . "\nFROM " . table($TABLE);
$from = ($select ? implode(", ", $select) : ($oid ? "$oid, " : "") . "*") . "\nFROM " . table($TABLE);
$group_by = ($group && count($group) < count($select) ? "\nGROUP BY " . implode(", ", $group) : "") . ($order ? "\nORDER BY " . implode(", ", $order) : "");
if ($_GET["val"] && is_ajax()) {
@@ -104,7 +106,7 @@ if ($_POST && !$error) {
$query = "INTO $query";
}
if ($_POST["all"] || ($unselected === array() && $_POST["check"]) || count($group) < count($select)) {
$result = queries($command . " $query" . ($_POST["all"] ? ($where ? "\nWHERE " . implode(" AND ", $where) : "") : "\nWHERE $where_check"));
$result = queries("$command $query" . ($_POST["all"] ? ($where ? "\nWHERE " . implode(" AND ", $where) : "") : "\nWHERE $where_check"));
$affected = $connection->affected_rows;
} else {
foreach ((array) $_POST["check"] as $val) {
@@ -117,7 +119,14 @@ if ($_POST && !$error) {
}
}
}
queries_redirect(remove_from_uri("page"), lang('%d item(s) have been affected.', $affected), $result);
$message = lang('%d item(s) have been affected.', $affected);
if ($_POST["clone"] && $result && $affected == 1) {
$last_id = last_id();
if ($last_id) {
$message = lang('Item%s has been inserted.', " $last_id");
}
}
queries_redirect(remove_from_uri("page"), $message, $result);
//! display edit page in case of an error
} elseif (!$_POST["import"]) { // modify
if (!$_POST["val"]) {
@@ -257,7 +266,7 @@ if (!$columns) {
reset($select);
$rank = 1;
foreach ($rows[0] as $key => $val) {
if ($table_status["Oid"] != "t" || $key != "oid") {
if ($key != $oid) {
$val = $_GET["columns"][key($select)];
$field = $fields[$select ? ($val ? $val["col"] : current($select)) : $key];
$name = ($field ? $adminer->fieldName($field, $rank) : "*");
@@ -266,8 +275,16 @@ if (!$columns) {
$names[$key] = $name;
$column = idf_escape($key);
$href = remove_from_uri('(order|desc)[^=]*|page') . '&order%5B0%5D=' . urlencode($key);
echo '<th><a href="' . h($href) . '">' . (!$select || $val ? apply_sql_function($val["fun"], $name) : h(current($select))) . "</a>"; //! columns looking like functions
echo "<a href='" . h("$href&desc%5B0%5D=1") . "' title='" . lang('descending') . "' class='text'> ↓</a>";
$desc = "&desc%5B0%5D=1";
echo '<th onmouseover="columnMouse(this);" onmouseout="columnMouse(this, \' hidden\');">';
echo '<a href="' . h($href . ($order[0] == $column || $order[0] == $key || (!$order && count($group) < count($select) && $group[0] == $column) ? $desc : '')) . '">'; // $order[0] == $key - COUNT(*)
echo (!$select || $val ? apply_sql_function($val["fun"], $name) : h(current($select))) . "</a>"; //! columns looking like functions
echo "<span class='column hidden'>";
echo "<a href='" . h($href . $desc) . "' title='" . lang('descending') . "' class='text'> ↓</a>";
if (!$val["fun"]) {
echo '<a href="#fieldset-search" onclick="selectSearch(\'' . h(js_escape($key)) . '\'); return false;" title="' . lang('Search') . '" class="text jsonly"> =</a>';
}
echo "</span>";
}
$functions[$key] = $val["fun"];
next($select);

View File

@@ -58,7 +58,7 @@ if (!$error && $_POST) {
$dump_format = $adminer->dumpFormat();
unset($dump_format["sql"]);
while ($query != "") {
if (!$offset && preg_match("~^$space*DELIMITER\\s+(.+)~i", $query, $match)) {
if (!$offset && preg_match("~^$space*DELIMITER\\s+(\\S+)~i", $query, $match)) {
$delimiter = $match[1];
$query = substr($query, strlen($match[0]));
} else {

View File

@@ -23,6 +23,7 @@ pre { margin: 1em 0 0; }
input[type=image] { vertical-align: middle; }
.version { color: #777; font-size: 67%; }
.js .hidden, .nojs .jsonly { display: none; }
.js .column { position: absolute; background: #ddf; padding: .3em 1ex .3em 0; margin-top: -.3em; }
.nowrap td, .nowrap th, td.nowrap { white-space: pre; }
.wrap td { white-space: normal; }
.error { color: red; background: #fee; }
@@ -44,8 +45,11 @@ input[type=image] { vertical-align: middle; }
.active { font-weight: bold; }
.sqlarea { width: 98%; }
.icon { width: 18px; height: 18px; }
#menu { position: absolute; margin: 10px 0 0; padding: 0 0 30px 0; top: 2em; left: 0; width: 19em; overflow: auto; overflow-y: hidden; white-space: nowrap; }
#menu { position: absolute; margin: 10px 0 0; padding: 0 0 30px 0; top: 2em; left: 0; width: 19em; white-space: nowrap; }
#menu p { padding: .8em 1em; margin: 0; border-bottom: 1px solid #ccc; }
#dbs { overflow: hidden; }
#logins, #tables { overflow: auto; }
#logins a, #tables a { background: #fff; }
#content { margin: 2em 0 0 21em; padding: 10px 20px 20px 0; }
#lang { position: absolute; top: 0; left: 0; line-height: 1.8em; padding: .3em 1em; }
#breadcrumb { white-space: nowrap; position: absolute; top: 0; left: 21em; background: #eee; height: 2em; line-height: 1.8em; padding: 0 1em; margin: 0 0 0 -18px; }

View File

@@ -64,7 +64,7 @@ function typePassword(el, disable) {
}
function loginDriver(driver) {
var trs = driver.parentNode.parentNode.parentNode.rows;
var trs = parentTag(driver, 'table').rows;
for (var i=1; i < trs.length - 1; i++) {
trs[i].className = (/sqlite/.test(driver.value) ? 'hidden' : '');
}
@@ -109,6 +109,64 @@ function textareaKeydown(target, event) {
/** Check whether the query will be executed with index
* @param HTMLFormElement
*/
function selectFieldChange(form) {
var ok = (function () {
var inputs = form.getElementsByTagName('input');
for (var i=0; i < inputs.length; i++) {
if (inputs[i].value && /^fulltext/.test(inputs[i].name)) {
return true;
}
}
var ok = form.limit.value;
var selects = form.getElementsByTagName('select');
var group = false;
var columns = {};
for (var i=0; i < selects.length; i++) {
var select = selects[i];
var col = selectValue(select);
var match = /^(where.+)col\]/.exec(select.name);
if (match) {
var op = selectValue(form[match[1] + 'op]']);
var val = form[match[1] + 'val]'].value;
if (col in indexColumns && (!/LIKE|REGEXP/.test(op) || (op == 'LIKE' && val.charAt(0) != '%'))) {
return true;
} else if (col || val) {
ok = false;
}
}
if ((match = /^(columns.+)fun\]/.exec(select.name))) {
if (/^(avg|count|count distinct|group_concat|max|min|sum)$/.test(col)) {
group = true;
}
var val = selectValue(form[match[1] + 'col]']);
if (val) {
columns[col && col != 'count' ? '' : val] = 1;
}
}
if (col && /^order/.test(select.name)) {
if (!(col in indexColumns)) {
ok = false;
}
break;
}
}
if (group) {
for (var col in columns) {
if (!(col in indexColumns)) {
ok = false;
}
}
}
return ok;
})();
setHtml('noindex', (ok ? '' : '!'));
}
var added = '.', rowCount;
/** Check if val is equal to a-delimiter-b where delimiter is '_', '' or big letter
@@ -178,7 +236,7 @@ function editingAddRow(button, allowed, focus) {
}
var match = /(\d+)(\.\d+)?/.exec(button.name);
var x = match[0] + (match[2] ? added.substr(match[2].length) : added) + '1';
var row = button.parentNode.parentNode;
var row = parentTag(button, 'tr');
var row2 = row.cloneNode(true);
var tags = row.getElementsByTagName('select');
var tags2 = row2.getElementsByTagName('select');
@@ -224,7 +282,7 @@ function editingAddRow(button, allowed, focus) {
function editingRemoveRow(button) {
var field = formField(button.form, button.name.replace(/drop_col(.+)/, 'fields$1[field]'));
field.parentNode.removeChild(field);
button.parentNode.parentNode.style.display = 'none';
parentTag(button, 'tr').style.display = 'none';
return true;
}
@@ -310,9 +368,9 @@ function partitionByChange(el) {
* @param HTMLInputElement
*/
function partitionNameChange(el) {
var row = el.parentNode.parentNode.cloneNode(true);
var row = parentTag(el, 'tr').cloneNode(true);
row.firstChild.firstChild.value = '';
el.parentNode.parentNode.parentNode.appendChild(row);
parentTag(el, 'table').appendChild(row);
el.onchange = function () {};
}
@@ -323,13 +381,13 @@ function partitionNameChange(el) {
*/
function foreignAddRow(field) {
field.onchange = function () { };
var row = field.parentNode.parentNode.cloneNode(true);
var row = parentTag(field, 'tr').cloneNode(true);
var selects = row.getElementsByTagName('select');
for (var i=0; i < selects.length; i++) {
selects[i].name = selects[i].name.replace(/\]/, '1$&');
selects[i].selectedIndex = 0;
}
field.parentNode.parentNode.parentNode.appendChild(row);
parentTag(field, 'table').appendChild(row);
}
@@ -339,8 +397,7 @@ function foreignAddRow(field) {
*/
function indexesAddRow(field) {
field.onchange = function () { };
var parent = field.parentNode.parentNode;
var row = parent.cloneNode(true);
var row = parentTag(field, 'tr').cloneNode(true);
var selects = row.getElementsByTagName('select');
for (var i=0; i < selects.length; i++) {
selects[i].name = selects[i].name.replace(/indexes\[\d+/, '$&1');
@@ -351,7 +408,7 @@ function indexesAddRow(field) {
inputs[i].name = inputs[i].name.replace(/indexes\[\d+/, '$&1');
inputs[i].value = '';
}
parent.parentNode.appendChild(row);
parentTag(field, 'table').appendChild(row);
}
/** Change column in index
@@ -359,7 +416,7 @@ function indexesAddRow(field) {
* @param string name prefix
*/
function indexesChangeColumn(field, prefix) {
var columns = field.parentNode.parentNode.getElementsByTagName('select');
var columns = parentTag(field, 'td').getElementsByTagName('select');
var names = [];
for (var i=0; i < columns.length; i++) {
var value = selectValue(columns[i]);
@@ -390,7 +447,7 @@ function indexesAddColumn(field, prefix) {
var input = column.getElementsByTagName('input')[0];
input.name = input.name.replace(/\]\[\d+/, '$&1');
input.value = '';
field.parentNode.parentNode.appendChild(column);
parentTag(field, 'td').appendChild(column);
field.onchange();
}

View File

@@ -38,11 +38,24 @@ function selectValue(select) {
return ((selected.attributes.value || {}).specified ? selected.value : selected.text);
}
/** Get parent node with specified tag name.
* @param HTMLElement
* @param string
* @return HTMLElement
*/
function parentTag(el, tag) {
var re = new RegExp('^' + tag + '$', 'i');
while (!re.test(el.tagName)) {
el = el.parentNode;
}
return el;
}
/** Set checked class
* @param HTMLInputElement
*/
function trCheck(el) {
var tr = el.parentNode.parentNode;
var tr = parentTag(el, 'tr');
tr.className = tr.className.replace(/(^|\s)checked(\s|$)/, '$2') + (el.checked ? ' checked' : '');
}
@@ -135,7 +148,7 @@ function checkboxClick(event, el) {
}
if (event.shiftKey && (!lastChecked || lastChecked.name == el.name)) {
var checked = (lastChecked ? lastChecked.checked : true);
var inputs = el.parentNode.parentNode.parentNode.getElementsByTagName('input');
var inputs = parentTag(el, 'table').getElementsByTagName('input');
var checking = !lastChecked;
for (var i=0; i < inputs.length; i++) {
var input = inputs[i];
@@ -152,8 +165,9 @@ function checkboxClick(event, el) {
}
}
}
} else {
lastChecked = el;
}
lastChecked = el;
}
/** Set HTML code of an element
@@ -195,6 +209,14 @@ function pageClick(href, page, event) {
}
}
function menuOver(el) {
el.style.overflow = 'visible';
}
function menuOut(el) {
el.style.overflow = 'auto';
}
/** Add row in select fieldset
@@ -220,44 +242,41 @@ function selectAddRow(field) {
field.parentNode.parentNode.appendChild(row);
}
/** Check whether the query will be executed with index
* @param HTMLFormElement
*/
function selectFieldChange(form) {
var ok = (function () {
var inputs = form.getElementsByTagName('input');
for (var i=0; i < inputs.length; i++) {
var input = inputs[i];
if (/^fulltext/.test(input.name) && input.value) {
return true;
}
/** Toggles column context menu
* @param HTMLElement
* @param [string] extra class name
*/
function columnMouse(el, className) {
var spans = el.getElementsByTagName('span');
for (var i=0; i < spans.length; i++) {
if (/column/.test(spans[i].className)) {
spans[i].className = 'column' + (className || '');
}
var ok = true;
var selects = form.getElementsByTagName('select');
for (var i=0; i < selects.length; i++) {
var select = selects[i];
var col = selectValue(select);
var match = /^(where.+)col\]/.exec(select.name);
if (match) {
var op = selectValue(form[match[1] + 'op]']);
var val = form[match[1] + 'val]'].value;
if (col in indexColumns && (!/LIKE|REGEXP/.test(op) || (op == 'LIKE' && val.charAt(0) != '%'))) {
return true;
} else if (col || val) {
ok = false;
}
}
//! take grouping in select into account
if (col && /^order/.test(select.name)) {
if (!(col in indexColumns)) {
ok = false;
}
break;
}
}
}
/** Fill column in search field
* @param string
*/
function selectSearch(name) {
var el = document.getElementById('fieldset-search');
el.className = '';
var divs = el.getElementsByTagName('div');
for (var i=0; i < divs.length; i++) {
var div = divs[i];
if (/select/i.test(div.firstChild.tagName) && selectValue(div.firstChild) == name) {
break;
}
return ok;
})();
setHtml('noindex', (ok ? '' : '!'));
}
if (i == divs.length) {
div.firstChild.value = name;
div.firstChild.onchange();
}
div.lastChild.focus();
}

View File

@@ -58,9 +58,7 @@ if ($fields) {
echo "(<i>" . implode("</i>, <i>", array_map('h', $foreign_key["target"])) . "</i>)";
echo "<td>" . nbsp($foreign_key["on_delete"]) . "\n";
echo "<td>" . nbsp($foreign_key["on_update"]) . "\n";
if ($jush != "sqlite") {
echo '<td><a href="' . h(ME . 'foreign=' . urlencode($TABLE) . '&name=' . urlencode($name)) . '">' . lang('Alter') . '</a>';
}
echo ($jush == "sqlite" ? "" : '<td><a href="' . h(ME . 'foreign=' . urlencode($TABLE) . '&name=' . urlencode($name)) . '">' . lang('Alter') . '</a>');
}
echo "</table>\n";
}

View File

@@ -1,3 +1,16 @@
Adminer 3.5.1 (released 2012-08-10):
Support same name fields in CSV export
Support Shift+click in export
Adminer 3.5.0 (released 2012-08-05):
Links for column search in select
Autohide column context menu in select
Autodisplay long table names in tables list
Display assigned auto_increment after clone
SQLite: Full alter table
SQLite: Better editing in tables without primary key
SQLite: Display number of rows in database overview
Adminer 3.4.0 (released 2012-06-30):
Link to descending order
Shift+click on checkbox to select consecutive rows

View File

@@ -193,7 +193,7 @@ ORDER BY ORDINAL_POSITION", null, "") as $row) { //! requires MySQL 5
function selectSearchPrint($where, $columns, $indexes) {
$where = (array) $_GET["where"];
echo '<fieldset><legend>' . lang('Search') . "</legend><div>\n";
echo '<fieldset id="fieldset-search"><legend>' . lang('Search') . "</legend><div>\n";
$keys = array();
foreach ($where as $key => $val) {
$keys[$val["col"]] = $key;
@@ -532,7 +532,7 @@ ORDER BY ORDINAL_POSITION", null, "") as $row) { //! requires MySQL 5
foreach ((array) $_SESSION["pwds"]["server"][""] as $username => $password) {
if ($password !== null) {
if ($first) {
echo "<p>\n";
echo "<p id='logins' onmouseover='menuOver(this);' onmouseout='menuOut(this);'>\n";
$first = false;
}
echo "<a href='" . h(auth_url("server", "", $username)) . "'>" . ($username != "" ? h($username) : "<i>" . lang('empty') . "</i>") . "</a><br>\n";
@@ -559,7 +559,7 @@ ORDER BY ORDINAL_POSITION", null, "") as $row) { //! requires MySQL 5
}
function tablesPrint($tables) {
echo "<p id='tables'>\n";
echo "<p id='tables' onmouseover='menuOver(this);' onmouseout='menuOut(this);'>\n";
foreach ($tables as $row) {
$name = $this->tableName($row);
if (isset($row["Engine"]) && $name != "") { // ignore views and tables without name

View File

@@ -3,6 +3,9 @@
function bodyLoad(version) {
}
function selectFieldChange(form) {
}
function whisperClick(event, field) {
var el = event.target || event.srcElement;
if (/^a$/i.test(el.tagName) && !(event.button || event.ctrlKey || event.shiftKey || event.altKey || event.metaKey)) {

View File

@@ -23,7 +23,7 @@ function tablesFilter(value) {
</script>
<p class="jsonly"><input onkeyup="tablesFilter(this.value);">
<?php
echo "<p id='tables'>\n";
echo "<p id='tables' onmouseover='menuOver(this);' onmouseout='menuOut(this);'>\n";
foreach ($tables as $table => $type) {
echo '<span><a href="' . h(ME) . 'select=' . urlencode($table) . '"' . bold($_GET["select"] == $table) . ">" . lang('select') . "</a> ";
echo '<a href="' . h(ME) . 'table=' . urlencode($table) . '"' . bold($_GET["table"] == $table) . ">" . h($table) . "</a><br></span>\n";

View File

@@ -38,7 +38,7 @@
</tr>
<tr>
<td>verifyTextPresent</td>
<td>1 item has been affected.</td>
<td>Item 2 has been inserted.</td>
<td></td>
</tr>

View File

@@ -3,7 +3,6 @@ Create view and routine options
Variables editation
Blob download and image display in edit form (important for Editor with hidden fields in select and SQL command)
Add title to Logout, edit (in select) and select (in menu) for style "hever"
Shift-click in checkboxes to select range
Export by GET parameters
Only first part of big BZ2 export is readable, files are missing in TAR
Draggable columns in alter table (thanks to Michal Manak)