1
0
mirror of https://github.com/vrana/adminer.git synced 2025-09-04 03:35:41 +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.')); query_redirect("DROP TABLE " . table($TABLE), substr(ME, 0, -1), lang('Table has been dropped.'));
} else { } else {
$fields = array(); $fields = array();
$all_fields = array();
$use_all_fields = false;
$foreign = array(); $foreign = array();
ksort($_POST["fields"]); ksort($_POST["fields"]);
$orig_field = reset($orig_fields); $orig_field = reset($orig_fields);
$after = "FIRST"; $after = " FIRST";
foreach ($_POST["fields"] as $key => $field) { foreach ($_POST["fields"] as $key => $field) {
$foreign_key = $foreign_keys[$field["type"]]; $foreign_key = $foreign_keys[$field["type"]];
$type_field = ($foreign_key !== null ? $referencable_primary[$foreign_key] : $field); //! can collide with user defined 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; $field["auto_increment"] = true;
} }
$process_field = process_field($field, $type_field); $process_field = process_field($field, $type_field);
$all_fields[] = array($field["orig"], $process_field, $after);
if ($process_field != process_field($orig_field, $orig_field)) { if ($process_field != process_field($orig_field, $orig_field)) {
$fields[] = array($field["orig"], $process_field, $after); $fields[] = array($field["orig"], $process_field, $after);
if ($field["orig"] != "" || $after) {
$use_all_fields = true;
}
} }
if ($foreign_key !== null) { 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"] != "") { } elseif ($field["orig"] != "") {
$use_all_fields = true;
$fields[] = array($field["orig"]); $fields[] = array($field["orig"]);
} }
if ($field["orig"] != "") { if ($field["orig"] != "") {
$orig_field = next($orig_fields); $orig_field = next($orig_fields);
if (!$orig_field) {
$after = "";
}
} }
} }
$partitioning = ""; $partitioning = "";
@@ -82,7 +92,7 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"] && !$_POST["up"]
queries_redirect(ME . "table=" . urlencode($name), $message, alter_table( queries_redirect(ME . "table=" . urlencode($name), $message, alter_table(
$TABLE, $TABLE,
$name, $name,
$fields, ($jush == "sqlite" && ($use_all_fields || $foreign) ? $all_fields : $fields),
$foreign, $foreign,
$_POST["Comment"], $_POST["Comment"],
($_POST["Engine"] && $_POST["Engine"] != $orig_status["Engine"] ? $_POST["Engine"] : ""), ($_POST["Engine"] && $_POST["Engine"] != $orig_status["Engine"] ? $_POST["Engine"] : ""),

View File

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

View File

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

View File

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

View File

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

View File

@@ -19,6 +19,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
function query($query) { function query($query) {
$result = @$this->_link->query($query); $result = @$this->_link->query($query);
$this->error = "";
if (!$result) { if (!$result) {
$this->error = $this->_link->lastErrorMsg(); $this->error = $this->_link->lastErrorMsg();
return false; return false;
@@ -93,6 +94,7 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
function query($query, $unbuffered = false) { function query($query, $unbuffered = false) {
$method = ($unbuffered ? "unbufferedQuery" : "query"); $method = ($unbuffered ? "unbufferedQuery" : "query");
$result = @$this->_link->$method($query, SQLITE_BOTH, $error); $result = @$this->_link->$method($query, SQLITE_BOTH, $error);
$this->error = "";
if (!$result) { if (!$result) {
$this->error = $error; $this->error = $error;
return false; return false;
@@ -248,9 +250,12 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
} }
function table_status($name = "") { function table_status($name = "") {
global $connection;
$return = array(); $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) { 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["Auto_increment"] = "";
$row["Rows"] = $connection->result("SELECT COUNT(*) FROM " . idf_escape($row["Name"]));
$return[$row["Name"]] = $row; $return[$row["Name"]] = $row;
} }
foreach (get_rows("SELECT * FROM sqlite_sequence", null, "") as $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) { function fk_support($table_status) {
global $connection; 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) { function fields($table) {
@@ -299,10 +304,12 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
$return[""] = array("type" => "PRIMARY", "columns" => $primary, "lengths" => array()); $return[""] = array("type" => "PRIMARY", "columns" => $primary, "lengths" => array());
} }
foreach (get_rows("PRAGMA index_list(" . table($table) . ")") as $row) { foreach (get_rows("PRAGMA index_list(" . table($table) . ")") as $row) {
$return[$row["name"]]["type"] = ($row["unique"] ? "UNIQUE" : "INDEX"); if (!ereg("^sqlite_", $row["name"])) {
$return[$row["name"]]["lengths"] = array(); $return[$row["name"]]["type"] = ($row["unique"] ? "UNIQUE" : "INDEX");
foreach (get_rows("PRAGMA index_info(" . idf_escape($row["name"]) . ")") as $row1) { $return[$row["name"]]["lengths"] = array();
$return[$row["name"]]["columns"][] = $row1["name"]; foreach (get_rows("PRAGMA index_info(" . idf_escape($row["name"]) . ")") as $row1) {
$return[$row["name"]]["columns"][] = $row1["name"];
}
} }
} }
return $return; 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) { function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
$alter = array(); $use_all_fields = ($table == "" || $foreign);
foreach ($fields as $field) { foreach ($fields as $field) {
if ($field[1]) { if ($field[0] != "" || !$field[1] || $field[2]) {
$alter[] = ($table != "" && $field[0] == "" ? "ADD " : " ") . implode($field[1]); $use_all_fields = true;
break;
} }
} }
$alter = array_merge($alter, $foreign); $alter = array();
if ($table != "") { $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) { foreach ($alter as $val) {
if (!queries("ALTER TABLE " . table($table) . " $val")) { if (!queries("ALTER TABLE " . table($table) . " $val")) {
return false; 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))) { if ($table != $name && !queries("ALTER TABLE " . table($table) . " RENAME TO " . table($name))) {
return false; return false;
} }
} elseif (!queries("CREATE TABLE " . table($name) . " (\n" . implode(",\n", $alter) . "\n)")) {
return false;
} }
if ($auto_increment) { if ($auto_increment) {
queries("UPDATE sqlite_sequence SET seq = $auto_increment WHERE name = " . q($name)); // ignores error 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) { 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"; $jush = "sqlite";

View File

@@ -48,14 +48,14 @@ SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
foreach (array("FUNCTION", "PROCEDURE") as $routine) { foreach (array("FUNCTION", "PROCEDURE") as $routine) {
foreach (get_rows("SHOW $routine STATUS WHERE Db = " . q($db), null, "-- ") as $row) { 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" : "") $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"]) { if ($_POST["events"]) {
foreach (get_rows("SHOW EVENTS", null, "-- ") as $row) { foreach (get_rows("SHOW EVENTS", null, "-- ") as $row) {
$out .= ($style != 'DROP+CREATE' ? "DROP EVENT IF EXISTS " . idf_escape($row["Name"]) . ";;\n" : "") $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) { if ($out) {
@@ -197,11 +197,11 @@ if (DB != "") {
$name = $table_status["Name"]; $name = $table_status["Name"];
$prefix = ereg_replace("_.*", "", $name); $prefix = ereg_replace("_.*", "", $name);
$checked = ($TABLE == "" || $TABLE == (substr($TABLE, -1) == "%" ? "$prefix%" : $name)); //! % may be part of table 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)) { if (is_view($table_status)) {
$views .= "$print\n"; $views .= "$print\n";
} else { } 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]++; $prefixes[$prefix]++;
} }

View File

@@ -53,7 +53,7 @@ if ($_POST["save"]) {
$select = array(); $select = array();
foreach ($fields as $name => $field) { foreach ($fields as $name => $field) {
if (isset($field["privileges"]["select"])) { 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(); $row = array();
@@ -76,7 +76,7 @@ if ($fields) {
echo "<tr><th>" . $adminer->fieldName($field); echo "<tr><th>" . $adminer->fieldName($field);
$default = $_GET["set"][bracket_escape($name)]; $default = $_GET["set"][bracket_escape($name)];
$value = ($row !== null $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"]))) : (!$update && $field["auto_increment"] ? "" : (isset($_GET["select"]) ? false : ($default !== null ? $default : $field["default"])))
); );
if (!$_POST["save"] && is_string($value)) { if (!$_POST["save"] && is_string($value)) {

View File

@@ -214,7 +214,7 @@ username.form['auth[driver]'].onchange();
foreach ($select as $key => $val) { foreach ($select as $key => $val) {
$val = $_GET["columns"][$key]; $val = $_GET["columns"][$key];
echo "<div>" . html_select("columns[$i][fun]", array(-1 => "") + $fun_group, $val["fun"]); 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++; $i++;
} }
echo "<div>" . html_select("columns[$i][fun]", array(-1 => "") + $fun_group, "", "this.nextSibling.nextSibling.onchange();"); 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) { function selectLimitPrint($limit) {
echo "<fieldset><legend>" . lang('Limit') . "</legend><div>"; // <div> for easy styling 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"; echo "</div></fieldset>\n";
} }
@@ -395,7 +395,7 @@ username.form['auth[driver]'].onchange();
// find anywhere // find anywhere
$cols = array(); $cols = array();
foreach ($fields as $name => $field) { 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); $name = idf_escape($name);
$cols[] = ($jush == "sql" && ereg('char|text|enum|set', $field["type"]) && !ereg('^utf8', $field["collation"]) ? "CONVERT($name USING utf8)" : $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"; echo "DROP " . ($is_view ? "VIEW" : "TABLE") . " IF EXISTS " . table($table) . ";\n";
} }
if ($is_view) { if ($is_view) {
// remove DEFINER with current user $create = remove_definer($create);
$create = preg_replace('~^([A-Z =]+) DEFINER=`' . preg_replace('~@(.*)~', '`@`(%|\\1)', logged_user()) . '`~', '\\1', $create); //! proper escaping of user
} }
echo ($style != "CREATE+ALTER" ? $create : ($is_view ? substr_replace($create, " OR REPLACE", 6, 0) : substr_replace($create, " IF NOT EXISTS", 12, 0))) . ";\n\n"; 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) { if ($result) {
$insert = ""; $insert = "";
$buffer = ""; $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 ($_POST["format"] != "sql") {
if ($style == "table") { if ($style == "table") {
dump_csv(array_keys($row)); dump_csv($keys);
$style = "INSERT"; $style = "INSERT";
} }
dump_csv($row); dump_csv($row);
} else { } else {
if (!$insert) { 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) { 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); $s = implode(",\t", $row);
if ($style == "INSERT+UPDATE") { if ($style == "INSERT+UPDATE") {
$set = array(); $set = array();
foreach ($row as $key => $val) { 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"; echo "$insert ($s) ON DUPLICATE KEY UPDATE " . implode(", ", $set) . ";\n";
} else { } else {
@@ -777,7 +783,7 @@ DROP PROCEDURE adminer_alter;
foreach ($usernames as $username => $password) { foreach ($usernames as $username => $password) {
if ($password !== null) { if ($password !== null) {
if ($first) { if ($first) {
echo "<p>\n"; echo "<p id='logins' onmouseover='menuOver(this);' onmouseout='menuOut(this);'>\n";
$first = false; $first = false;
} }
echo "<a href='" . h(auth_url($driver, $server, $username)) . "'>($drivers[$driver]) " . h($username . ($server != "" ? "@$server" : "")) . "</a><br>\n"; 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> </p>
</form> </form>
<form action=""> <form action="">
<p> <p id="dbs">
<?php hidden_fields_get(); ?> <?php hidden_fields_get(); ?>
<?php echo ($databases ? html_select("db", array("" => "(" . lang('database') . ")") + $databases, DB, "this.form.submit();") : '<input name="db" value="' . h(DB) . '">'); ?> <?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'" : ""); ?>> <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"]); 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="">' echo (isset($_GET["sql"]) ? '<input type="hidden" name="sql" value="">'
: (isset($_GET["schema"]) ? '<input type="hidden" name="schema" value="">' : (isset($_GET["schema"]) ? '<input type="hidden" name="schema" value="">'
: (isset($_GET["dump"]) ? '<input type="hidden" name="dump" value="">' : (isset($_GET["dump"]) ? '<input type="hidden" name="dump" value="">'
: ""))); : "")));
echo "</p></form>\n"; 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 * @return null
*/ */
function tablesPrint($tables) { function tablesPrint($tables) {
echo "<p id='tables'>\n"; echo "<p id='tables' onmouseover='menuOver(this);' onmouseout='menuOut(this);'>\n";
foreach ($tables as $table => $type) { 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) . '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 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; 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 /** Get string to add a file in TAR
* @param string * @param string
* @param string * @param string

View File

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

View File

@@ -1,2 +1,2 @@
<?php <?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) : ""); echo "<tr" . odd() . ">" . (support("kill") ? "<td>" . checkbox("kill[]", $row["Id"], 0) : "");
foreach ($row as $key => $val) { foreach ($row as $key => $val) {
echo "<td>" . ( 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 == "pgsql" && $key == "current_query" && $val != "<IDLE>") ||
($jush == "oracle" && $key == "sql_text" && $val != "") ($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>' ? "<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) { foreach ($sums + array("Auto_increment" => 0, "Rows" => 0) as $key => $val) {
if ($table_status[$key] != "") { if ($table_status[$key] != "") {
$val = number_format($table_status[$key], 0, '.', lang(',')); $val = number_format($table_status[$key], 0, '.', lang(','));
json_row("$key-$id", ($key == "Rows" && $val && ( json_row("$key-$id", ($key == "Rows" && $val && $table_status["Engine"] == ($sql == "pgsql" ? "table" : "InnoDB")
$table_status["Engine"] == "InnoDB" || // MySQL InnoDB ? "~ $val"
$table_status["Engine"] == "table" // PostgreSQL table reltype : $val
) ? "~ $val" : $val)); ));
if (isset($sums[$key])) { if (isset($sums[$key])) {
// ignore innodb_file_per_table because it is not active for tables created before it was enabled // 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); $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); $indexes = indexes($TABLE);
$fields = fields($TABLE); $fields = fields($TABLE);
$foreign_keys = column_foreign_keys($TABLE); $foreign_keys = column_foreign_keys($TABLE);
$oid = "";
if ($table_status["Oid"] == "t") { 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); parse_str($_COOKIE["adminer_import"], $adminer_import);
@@ -27,7 +29,7 @@ list($select, $group) = $adminer->selectColumnsProcess($columns, $indexes);
$where = $adminer->selectSearchProcess($fields, $indexes); $where = $adminer->selectSearchProcess($fields, $indexes);
$order = $adminer->selectOrderProcess($fields, $indexes); $order = $adminer->selectOrderProcess($fields, $indexes);
$limit = $adminer->selectLimitProcess(); $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) : ""); $group_by = ($group && count($group) < count($select) ? "\nGROUP BY " . implode(", ", $group) : "") . ($order ? "\nORDER BY " . implode(", ", $order) : "");
if ($_GET["val"] && is_ajax()) { if ($_GET["val"] && is_ajax()) {
@@ -104,7 +106,7 @@ if ($_POST && !$error) {
$query = "INTO $query"; $query = "INTO $query";
} }
if ($_POST["all"] || ($unselected === array() && $_POST["check"]) || count($group) < count($select)) { 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; $affected = $connection->affected_rows;
} else { } else {
foreach ((array) $_POST["check"] as $val) { 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 //! display edit page in case of an error
} elseif (!$_POST["import"]) { // modify } elseif (!$_POST["import"]) { // modify
if (!$_POST["val"]) { if (!$_POST["val"]) {
@@ -257,7 +266,7 @@ if (!$columns) {
reset($select); reset($select);
$rank = 1; $rank = 1;
foreach ($rows[0] as $key => $val) { foreach ($rows[0] as $key => $val) {
if ($table_status["Oid"] != "t" || $key != "oid") { if ($key != $oid) {
$val = $_GET["columns"][key($select)]; $val = $_GET["columns"][key($select)];
$field = $fields[$select ? ($val ? $val["col"] : current($select)) : $key]; $field = $fields[$select ? ($val ? $val["col"] : current($select)) : $key];
$name = ($field ? $adminer->fieldName($field, $rank) : "*"); $name = ($field ? $adminer->fieldName($field, $rank) : "*");
@@ -266,8 +275,16 @@ if (!$columns) {
$names[$key] = $name; $names[$key] = $name;
$column = idf_escape($key); $column = idf_escape($key);
$href = remove_from_uri('(order|desc)[^=]*|page') . '&order%5B0%5D=' . urlencode($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 $desc = "&desc%5B0%5D=1";
echo "<a href='" . h("$href&desc%5B0%5D=1") . "' title='" . lang('descending') . "' class='text'> ↓</a>"; 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"]; $functions[$key] = $val["fun"];
next($select); next($select);

View File

@@ -58,7 +58,7 @@ if (!$error && $_POST) {
$dump_format = $adminer->dumpFormat(); $dump_format = $adminer->dumpFormat();
unset($dump_format["sql"]); unset($dump_format["sql"]);
while ($query != "") { 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]; $delimiter = $match[1];
$query = substr($query, strlen($match[0])); $query = substr($query, strlen($match[0]));
} else { } else {

View File

@@ -23,6 +23,7 @@ pre { margin: 1em 0 0; }
input[type=image] { vertical-align: middle; } input[type=image] { vertical-align: middle; }
.version { color: #777; font-size: 67%; } .version { color: #777; font-size: 67%; }
.js .hidden, .nojs .jsonly { display: none; } .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; } .nowrap td, .nowrap th, td.nowrap { white-space: pre; }
.wrap td { white-space: normal; } .wrap td { white-space: normal; }
.error { color: red; background: #fee; } .error { color: red; background: #fee; }
@@ -44,8 +45,11 @@ input[type=image] { vertical-align: middle; }
.active { font-weight: bold; } .active { font-weight: bold; }
.sqlarea { width: 98%; } .sqlarea { width: 98%; }
.icon { width: 18px; height: 18px; } .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; } #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; } #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; } #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; } #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) { 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++) { for (var i=1; i < trs.length - 1; i++) {
trs[i].className = (/sqlite/.test(driver.value) ? 'hidden' : ''); 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; var added = '.', rowCount;
/** Check if val is equal to a-delimiter-b where delimiter is '_', '' or big letter /** 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 match = /(\d+)(\.\d+)?/.exec(button.name);
var x = match[0] + (match[2] ? added.substr(match[2].length) : added) + '1'; 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 row2 = row.cloneNode(true);
var tags = row.getElementsByTagName('select'); var tags = row.getElementsByTagName('select');
var tags2 = row2.getElementsByTagName('select'); var tags2 = row2.getElementsByTagName('select');
@@ -224,7 +282,7 @@ function editingAddRow(button, allowed, focus) {
function editingRemoveRow(button) { function editingRemoveRow(button) {
var field = formField(button.form, button.name.replace(/drop_col(.+)/, 'fields$1[field]')); var field = formField(button.form, button.name.replace(/drop_col(.+)/, 'fields$1[field]'));
field.parentNode.removeChild(field); field.parentNode.removeChild(field);
button.parentNode.parentNode.style.display = 'none'; parentTag(button, 'tr').style.display = 'none';
return true; return true;
} }
@@ -310,9 +368,9 @@ function partitionByChange(el) {
* @param HTMLInputElement * @param HTMLInputElement
*/ */
function partitionNameChange(el) { function partitionNameChange(el) {
var row = el.parentNode.parentNode.cloneNode(true); var row = parentTag(el, 'tr').cloneNode(true);
row.firstChild.firstChild.value = ''; row.firstChild.firstChild.value = '';
el.parentNode.parentNode.parentNode.appendChild(row); parentTag(el, 'table').appendChild(row);
el.onchange = function () {}; el.onchange = function () {};
} }
@@ -323,13 +381,13 @@ function partitionNameChange(el) {
*/ */
function foreignAddRow(field) { function foreignAddRow(field) {
field.onchange = function () { }; field.onchange = function () { };
var row = field.parentNode.parentNode.cloneNode(true); var row = parentTag(field, 'tr').cloneNode(true);
var selects = row.getElementsByTagName('select'); var selects = row.getElementsByTagName('select');
for (var i=0; i < selects.length; i++) { for (var i=0; i < selects.length; i++) {
selects[i].name = selects[i].name.replace(/\]/, '1$&'); selects[i].name = selects[i].name.replace(/\]/, '1$&');
selects[i].selectedIndex = 0; 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) { function indexesAddRow(field) {
field.onchange = function () { }; field.onchange = function () { };
var parent = field.parentNode.parentNode; var row = parentTag(field, 'tr').cloneNode(true);
var row = parent.cloneNode(true);
var selects = row.getElementsByTagName('select'); var selects = row.getElementsByTagName('select');
for (var i=0; i < selects.length; i++) { for (var i=0; i < selects.length; i++) {
selects[i].name = selects[i].name.replace(/indexes\[\d+/, '$&1'); 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].name = inputs[i].name.replace(/indexes\[\d+/, '$&1');
inputs[i].value = ''; inputs[i].value = '';
} }
parent.parentNode.appendChild(row); parentTag(field, 'table').appendChild(row);
} }
/** Change column in index /** Change column in index
@@ -359,7 +416,7 @@ function indexesAddRow(field) {
* @param string name prefix * @param string name prefix
*/ */
function indexesChangeColumn(field, prefix) { function indexesChangeColumn(field, prefix) {
var columns = field.parentNode.parentNode.getElementsByTagName('select'); var columns = parentTag(field, 'td').getElementsByTagName('select');
var names = []; var names = [];
for (var i=0; i < columns.length; i++) { for (var i=0; i < columns.length; i++) {
var value = selectValue(columns[i]); var value = selectValue(columns[i]);
@@ -390,7 +447,7 @@ function indexesAddColumn(field, prefix) {
var input = column.getElementsByTagName('input')[0]; var input = column.getElementsByTagName('input')[0];
input.name = input.name.replace(/\]\[\d+/, '$&1'); input.name = input.name.replace(/\]\[\d+/, '$&1');
input.value = ''; input.value = '';
field.parentNode.parentNode.appendChild(column); parentTag(field, 'td').appendChild(column);
field.onchange(); field.onchange();
} }

View File

@@ -38,11 +38,24 @@ function selectValue(select) {
return ((selected.attributes.value || {}).specified ? selected.value : selected.text); 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 /** Set checked class
* @param HTMLInputElement * @param HTMLInputElement
*/ */
function trCheck(el) { 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' : ''); 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)) { if (event.shiftKey && (!lastChecked || lastChecked.name == el.name)) {
var checked = (lastChecked ? lastChecked.checked : true); var checked = (lastChecked ? lastChecked.checked : true);
var inputs = el.parentNode.parentNode.parentNode.getElementsByTagName('input'); var inputs = parentTag(el, 'table').getElementsByTagName('input');
var checking = !lastChecked; var checking = !lastChecked;
for (var i=0; i < inputs.length; i++) { for (var i=0; i < inputs.length; i++) {
var input = inputs[i]; var input = inputs[i];
@@ -152,8 +165,9 @@ function checkboxClick(event, el) {
} }
} }
} }
} else {
lastChecked = el;
} }
lastChecked = el;
} }
/** Set HTML code of an element /** 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 /** Add row in select fieldset
@@ -220,44 +242,41 @@ function selectAddRow(field) {
field.parentNode.parentNode.appendChild(row); field.parentNode.parentNode.appendChild(row);
} }
/** Check whether the query will be executed with index
* @param HTMLFormElement
*/ /** Toggles column context menu
function selectFieldChange(form) { * @param HTMLElement
var ok = (function () { * @param [string] extra class name
var inputs = form.getElementsByTagName('input'); */
for (var i=0; i < inputs.length; i++) { function columnMouse(el, className) {
var input = inputs[i]; var spans = el.getElementsByTagName('span');
if (/^fulltext/.test(input.name) && input.value) { for (var i=0; i < spans.length; i++) {
return true; 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); /** Fill column in search field
if (match) { * @param string
var op = selectValue(form[match[1] + 'op]']); */
var val = form[match[1] + 'val]'].value; function selectSearch(name) {
if (col in indexColumns && (!/LIKE|REGEXP/.test(op) || (op == 'LIKE' && val.charAt(0) != '%'))) { var el = document.getElementById('fieldset-search');
return true; el.className = '';
} else if (col || val) { var divs = el.getElementsByTagName('div');
ok = false; for (var i=0; i < divs.length; i++) {
} var div = divs[i];
} if (/select/i.test(div.firstChild.tagName) && selectValue(div.firstChild) == name) {
//! take grouping in select into account break;
if (col && /^order/.test(select.name)) {
if (!(col in indexColumns)) {
ok = false;
}
break;
}
} }
return ok; }
})(); if (i == divs.length) {
setHtml('noindex', (ok ? '' : '!')); 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 "(<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_delete"]) . "\n";
echo "<td>" . nbsp($foreign_key["on_update"]) . "\n"; echo "<td>" . nbsp($foreign_key["on_update"]) . "\n";
if ($jush != "sqlite") { echo ($jush == "sqlite" ? "" : '<td><a href="' . h(ME . 'foreign=' . urlencode($TABLE) . '&name=' . urlencode($name)) . '">' . lang('Alter') . '</a>');
echo '<td><a href="' . h(ME . 'foreign=' . urlencode($TABLE) . '&name=' . urlencode($name)) . '">' . lang('Alter') . '</a>';
}
} }
echo "</table>\n"; 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): Adminer 3.4.0 (released 2012-06-30):
Link to descending order Link to descending order
Shift+click on checkbox to select consecutive rows 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) { function selectSearchPrint($where, $columns, $indexes) {
$where = (array) $_GET["where"]; $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(); $keys = array();
foreach ($where as $key => $val) { foreach ($where as $key => $val) {
$keys[$val["col"]] = $key; $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) { foreach ((array) $_SESSION["pwds"]["server"][""] as $username => $password) {
if ($password !== null) { if ($password !== null) {
if ($first) { if ($first) {
echo "<p>\n"; echo "<p id='logins' onmouseover='menuOver(this);' onmouseout='menuOut(this);'>\n";
$first = false; $first = false;
} }
echo "<a href='" . h(auth_url("server", "", $username)) . "'>" . ($username != "" ? h($username) : "<i>" . lang('empty') . "</i>") . "</a><br>\n"; 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) { function tablesPrint($tables) {
echo "<p id='tables'>\n"; echo "<p id='tables' onmouseover='menuOver(this);' onmouseout='menuOut(this);'>\n";
foreach ($tables as $row) { foreach ($tables as $row) {
$name = $this->tableName($row); $name = $this->tableName($row);
if (isset($row["Engine"]) && $name != "") { // ignore views and tables without name if (isset($row["Engine"]) && $name != "") { // ignore views and tables without name

View File

@@ -3,6 +3,9 @@
function bodyLoad(version) { function bodyLoad(version) {
} }
function selectFieldChange(form) {
}
function whisperClick(event, field) { function whisperClick(event, field) {
var el = event.target || event.srcElement; var el = event.target || event.srcElement;
if (/^a$/i.test(el.tagName) && !(event.button || event.ctrlKey || event.shiftKey || event.altKey || event.metaKey)) { 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> </script>
<p class="jsonly"><input onkeyup="tablesFilter(this.value);"> <p class="jsonly"><input onkeyup="tablesFilter(this.value);">
<?php <?php
echo "<p id='tables'>\n"; echo "<p id='tables' onmouseover='menuOver(this);' onmouseout='menuOut(this);'>\n";
foreach ($tables as $table => $type) { foreach ($tables as $table => $type) {
echo '<span><a href="' . h(ME) . 'select=' . urlencode($table) . '"' . bold($_GET["select"] == $table) . ">" . lang('select') . "</a> "; 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"; 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>
<tr> <tr>
<td>verifyTextPresent</td> <td>verifyTextPresent</td>
<td>1 item has been affected.</td> <td>Item 2 has been inserted.</td>
<td></td> <td></td>
</tr> </tr>

View File

@@ -3,7 +3,6 @@ Create view and routine options
Variables editation Variables editation
Blob download and image display in edit form (important for Editor with hidden fields in select and SQL command) 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" 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 Export by GET parameters
Only first part of big BZ2 export is readable, files are missing in TAR Only first part of big BZ2 export is readable, files are missing in TAR
Draggable columns in alter table (thanks to Michal Manak) Draggable columns in alter table (thanks to Michal Manak)