Reintegrate sqlite branch
git-svn-id: https://adminer.svn.sourceforge.net/svnroot/adminer/trunk@1466 7c3ca157-0c34-0410-bff1-cbf682f78f5c
This commit is contained in:
parent
2df25baa3c
commit
3f5b683456
|
@ -28,7 +28,9 @@ if (!$error && $_POST) {
|
|||
}
|
||||
$call[] = (isset($out[$key]) ? "@" . idf_escape($field["field"]) : $val);
|
||||
}
|
||||
if (!$connection->multi_query((isset($_GET["callf"]) ? "SELECT" : "CALL") . " " . idf_escape($PROCEDURE) . "(" . implode(", ", $call) . ")")) {
|
||||
$query = (isset($_GET["callf"]) ? "SELECT" : "CALL") . " " . idf_escape($PROCEDURE) . "(" . implode(", ", $call) . ")";
|
||||
echo "<p><code class='jush-$driver'>" . h($query) . "</code> <a href='" . h(ME) . "sql=" . urlencode($query) . "'>" . lang('Edit') . "</a>\n";
|
||||
if (!$connection->multi_query($query)) {
|
||||
echo "<p class='error'>" . error() . "\n";
|
||||
} else {
|
||||
do {
|
||||
|
@ -52,8 +54,9 @@ if ($in) {
|
|||
echo "<table cellspacing='0'>\n";
|
||||
foreach ($in as $key) {
|
||||
$field = $routine["fields"][$key];
|
||||
echo "<tr><th>" . h($field["field"]);
|
||||
$value = $_POST["fields"][$key];
|
||||
$name = $field["field"];
|
||||
echo "<tr><th>" . h($name);
|
||||
$value = $_POST["fields"][$name];
|
||||
if ($value != "" && ereg("enum|set", $field["type"])) {
|
||||
$value = intval($value);
|
||||
}
|
||||
|
|
|
@ -19,20 +19,8 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"] && !$_POST["up"]
|
|||
if ($_POST["drop"]) {
|
||||
query_redirect("DROP TABLE " . idf_escape($_GET["create"]), substr(ME, 0, -1), lang('Table has been dropped.'));
|
||||
} else {
|
||||
$auto_increment_index = " PRIMARY KEY";
|
||||
// don't overwrite primary key by auto_increment
|
||||
if ($TABLE != "" && $_POST["auto_increment_col"]) {
|
||||
foreach (indexes($TABLE) as $index) {
|
||||
if (in_array($_POST["fields"][$_POST["auto_increment_col"]]["orig"], $index["columns"], true)) {
|
||||
$auto_increment_index = "";
|
||||
break;
|
||||
}
|
||||
if ($index["type"] == "PRIMARY") {
|
||||
$auto_increment_index = " UNIQUE";
|
||||
}
|
||||
}
|
||||
}
|
||||
$fields = "";
|
||||
$fields = array();
|
||||
$foreign = array();
|
||||
ksort($_POST["fields"]);
|
||||
$orig_field = reset($orig_fields);
|
||||
$after = "FIRST";
|
||||
|
@ -48,33 +36,26 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"] && !$_POST["up"]
|
|||
$field["on_update"] = "CURRENT_TIMESTAMP";
|
||||
$field["default"] = $default;
|
||||
}
|
||||
if ($key == $_POST["auto_increment_col"]) {
|
||||
$field["auto_increment"] = true;
|
||||
}
|
||||
$process_field = process_field($field, $type_field);
|
||||
$auto_increment = ($key == $_POST["auto_increment_col"]);
|
||||
if ($process_field != process_field($orig_field, $orig_field) || $orig_field["auto_increment"] != $auto_increment) {
|
||||
$fields .= "\n" . ($TABLE != "" ? ($field["orig"] != "" ? "CHANGE " . idf_escape($field["orig"]) : "ADD") : " ")
|
||||
. " $process_field"
|
||||
. ($auto_increment ? " AUTO_INCREMENT$auto_increment_index" : "")
|
||||
. ($TABLE != "" ? " $after" : "") . ","
|
||||
;
|
||||
if ($process_field != process_field($orig_field, $orig_field)) {
|
||||
$fields[] = array($field["orig"], $process_field, $after);
|
||||
}
|
||||
if (!isset($types[$field["type"]])) {
|
||||
$fields .= ($TABLE != "" ? "\nADD" : "") . " FOREIGN KEY (" . idf_escape($field["field"]) . ") REFERENCES " . idf_escape($foreign_keys[$field["type"]]) . " (" . idf_escape($type_field["field"]) . "),";
|
||||
$foreign[] = ($TABLE != "" ? "ADD " : " ") . "FOREIGN KEY (" . idf_escape($field["field"]) . ") REFERENCES " . idf_escape($foreign_keys[$field["type"]]) . " (" . idf_escape($type_field["field"]) . ")";
|
||||
}
|
||||
}
|
||||
$after = "AFTER " . idf_escape($field["field"]);
|
||||
//! drop and create foreign keys with renamed columns
|
||||
} elseif ($field["orig"] != "") {
|
||||
$fields .= "\nDROP " . idf_escape($field["orig"]) . ",";
|
||||
$fields[] = array($field["orig"]);
|
||||
}
|
||||
if ($field["orig"] != "") {
|
||||
$orig_field = next($orig_fields);
|
||||
}
|
||||
}
|
||||
$status = "COMMENT=" . $connection->quote($_POST["Comment"])
|
||||
. ($_POST["Engine"] && $_POST["Engine"] != $orig_status["Engine"] ? " ENGINE=" . $connection->quote($_POST["Engine"]) : "")
|
||||
. ($_POST["Collation"] && $_POST["Collation"] != $orig_status["Collation"] ? " COLLATE " . $connection->quote($_POST["Collation"]) : "")
|
||||
. ($_POST["Auto_increment"] != "" ? " AUTO_INCREMENT=" . preg_replace('~[^0-9]+~', '', $_POST["Auto_increment"]) : "")
|
||||
;
|
||||
$partitioning = "";
|
||||
if (in_array($_POST["partition_by"], $partition_by)) {
|
||||
$partitions = array();
|
||||
if ($_POST["partition_by"] == 'RANGE' || $_POST["partition_by"] == 'LIST') {
|
||||
|
@ -83,20 +64,29 @@ if ($_POST && !$error && !$_POST["add"] && !$_POST["drop_col"] && !$_POST["up"]
|
|||
$partitions[] = "\nPARTITION " . idf_escape($val) . " VALUES " . ($_POST["partition_by"] == 'RANGE' ? "LESS THAN" : "IN") . ($value != "" ? " ($value)" : " MAXVALUE"); //! SQL injection
|
||||
}
|
||||
}
|
||||
$status .= "\nPARTITION BY $_POST[partition_by]($_POST[partition])" . ($partitions // $_POST["partition"] can be expression, not only column
|
||||
$partitioning .= "\nPARTITION BY $_POST[partition_by]($_POST[partition])" . ($partitions // $_POST["partition"] can be expression, not only column
|
||||
? " (" . implode(",", $partitions) . "\n)"
|
||||
: ($_POST["partitions"] ? " PARTITIONS " . intval($_POST["partitions"]) : "")
|
||||
);
|
||||
} elseif ($connection->server_info >= 5.1 && $TABLE != "") {
|
||||
$status .= "\nREMOVE PARTITIONING";
|
||||
} elseif ($TABLE != "") {
|
||||
$partitioning .= "\nREMOVE PARTITIONING";
|
||||
}
|
||||
$location = ME . "table=" . urlencode($_POST["name"]);
|
||||
if ($TABLE != "") {
|
||||
query_redirect("ALTER TABLE " . idf_escape($TABLE) . "$fields\nRENAME TO " . idf_escape($_POST["name"]) . ",\n$status", $location, lang('Table has been altered.'));
|
||||
} else {
|
||||
$message = lang('Table has been altered.');
|
||||
if ($TABLE == "") {
|
||||
cookie("adminer_engine", $_POST["Engine"]);
|
||||
query_redirect("CREATE TABLE " . idf_escape($_POST["name"]) . " (" . substr($fields, 0, -1) . "\n) $status", $location, lang('Table has been created.'));
|
||||
$message = lang('Table has been created.');
|
||||
}
|
||||
queries_redirect(ME . "table=" . urlencode($_POST["name"]), $message, alter_table(
|
||||
$TABLE,
|
||||
$_POST["name"],
|
||||
$fields,
|
||||
$foreign,
|
||||
$_POST["Comment"],
|
||||
($_POST["Engine"] && $_POST["Engine"] != $orig_status["Engine"] ? $_POST["Engine"] : ""),
|
||||
($_POST["Collation"] && $_POST["Collation"] != $orig_status["Collation"] ? $_POST["Collation"] : ""),
|
||||
($_POST["Auto_increment"] != "" ? preg_replace('~[^0-9]+~', '', $_POST["Auto_increment"]) : ""),
|
||||
$partitioning
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,9 +117,9 @@ if ($_POST) {
|
|||
}
|
||||
$row["fields"][] = $field;
|
||||
}
|
||||
if ($connection->server_info >= 5.1) {
|
||||
if (support("partitioning")) {
|
||||
$from = "FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = " . $connection->quote(DB) . " AND TABLE_NAME = " . $connection->quote($TABLE);
|
||||
$result = $connection->query("SELECT PARTITION_METHOD, PARTITION_ORDINAL_POSITION, PARTITION_EXPRESSION $from ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1");
|
||||
$result = $connection->query("SELECT" . limit("PARTITION_METHOD, PARTITION_ORDINAL_POSITION, PARTITION_EXPRESSION $from ORDER BY PARTITION_ORDINAL_POSITION", 1));
|
||||
list($row["partition_by"], $row["partitions"], $row["partition"]) = $result->fetch_row();
|
||||
$row["partition_names"] = array();
|
||||
$row["partition_values"] = array();
|
||||
|
@ -162,24 +152,23 @@ foreach ($engines as $engine) {
|
|||
<p>
|
||||
<?php echo lang('Table name'); ?>: <input name="name" maxlength="64" value="<?php echo h($row["name"]); ?>">
|
||||
<?php echo ($engines ? html_select("Engine", array("" => "(" . lang('engine') . ")") + $engines, $row["Engine"]) : ""); ?>
|
||||
<?php echo html_select("Collation", array("" => "(" . lang('collation') . ")") + $collations, $row["Collation"]); ?>
|
||||
<?php echo ($collations ? html_select("Collation", array("" => "(" . lang('collation') . ")") + $collations, $row["Collation"]) : ""); ?>
|
||||
<input type="submit" value="<?php echo lang('Save'); ?>">
|
||||
<table cellspacing="0" id="edit-fields" class="nowrap">
|
||||
<?php $column_comments = edit_fields($row["fields"], $collations, "TABLE", $suhosin, $foreign_keys); ?>
|
||||
<?php $comments = edit_fields($row["fields"], $collations, "TABLE", $suhosin, $foreign_keys, $row["Comment"] != ""); ?>
|
||||
</table>
|
||||
<p>
|
||||
<?php echo lang('Auto Increment'); ?>: <input name="Auto_increment" size="6" value="<?php echo h($row["Auto_increment"]); ?>">
|
||||
<?php echo lang('Comment'); ?>: <input name="Comment" value="<?php echo h($row["Comment"]); ?>" maxlength="60">
|
||||
<script type="text/javascript">
|
||||
document.write('<label><input type="checkbox" onclick="columnShow(this.checked, 5);"><?php echo lang('Default values'); ?><\/label>');
|
||||
document.write('<label><input type="checkbox"<?php if ($column_comments) { ?> checked<?php } ?> onclick="columnShow(this.checked, 6);"><?php echo lang('Show column comments'); ?><\/label>');
|
||||
</script>
|
||||
<?php echo (support("comment") ? checkbox("", "", $comments, lang('Comment'), "columnShow(this.checked, 6); toggle('Comment');") . ' <input id="Comment" name="Comment" value="' . h($row["Comment"]) . '" maxlength="60"' . ($comments ? '' : ' class="hidden"') . '>' : ''); ?>
|
||||
<p>
|
||||
<input type="hidden" name="token" value="<?php echo $token; ?>">
|
||||
<input type="submit" value="<?php echo lang('Save'); ?>">
|
||||
<?php if (strlen($_GET["create"])) { ?><input type="submit" name="drop" value="<?php echo lang('Drop'); ?>"<?php echo $confirm; ?>><?php } ?>
|
||||
<?php
|
||||
if ($connection->server_info >= 5.1) {
|
||||
if (support("partitioning")) {
|
||||
$partition_table = ereg('RANGE|LIST', $row["partition_by"]);
|
||||
print_fieldset("partition", lang('Partition by'), $row["partition_by"]);
|
||||
?>
|
||||
|
|
|
@ -2,35 +2,26 @@
|
|||
if ($_POST && !$error && !isset($_POST["add_x"])) { // add is an image and PHP changes add.x to add_x
|
||||
restart_session();
|
||||
if ($_POST["drop"]) {
|
||||
unset($_SESSION["databases"][$_GET["server"]]);
|
||||
set_session("databases", null);
|
||||
query_redirect("DROP DATABASE " . idf_escape(DB), remove_from_uri("db|database"), lang('Database has been dropped.'));
|
||||
} elseif (DB !== $_POST["name"]) {
|
||||
// create or rename database
|
||||
unset($_SESSION["databases"][$_GET["server"]]); // clear cache
|
||||
$dbs = explode("\n", str_replace("\r", "", $_POST["name"]));
|
||||
$failed = false;
|
||||
$last = "";
|
||||
foreach ($dbs as $db) {
|
||||
if (count($dbs) == 1 || $db != "") { // ignore empty lines but always try to create single database
|
||||
if (!queries("CREATE DATABASE " . idf_escape($db) . ($_POST["collation"] ? " COLLATE " . $connection->quote($_POST["collation"]) : ""))) {
|
||||
$failed = true;
|
||||
}
|
||||
$last = $db;
|
||||
}
|
||||
}
|
||||
if (query_redirect(queries(), ME . "db=" . urlencode($last), lang('Database has been created.'), DB == "", false, $failed)) {
|
||||
//! move triggers
|
||||
$result = $connection->query("SHOW TABLES");
|
||||
while ($row = $result->fetch_row()) {
|
||||
if (!queries("RENAME TABLE " . idf_escape($row[0]) . " TO " . idf_escape($_POST["name"]) . "." . idf_escape($row[0]))) {
|
||||
break;
|
||||
set_session("databases", null); // clear cache
|
||||
if (DB != "") {
|
||||
queries_redirect(preg_replace('~db=[^&]*&~', '', ME) . "db=" . urlencode($_POST["name"]), lang('Database has been renamed.'), rename_database($_POST["name"], $_POST["collation"]));
|
||||
} else {
|
||||
$dbs = explode("\n", str_replace("\r", "", $_POST["name"]));
|
||||
$success = true;
|
||||
$last = "";
|
||||
foreach ($dbs as $db) {
|
||||
if (count($dbs) == 1 || $db != "") { // ignore empty lines but always try to create single database
|
||||
if (!queries("CREATE DATABASE " . idf_escape($db) . ($_POST["collation"] ? " COLLATE " . $connection->quote($_POST["collation"]) : ""))) {
|
||||
$success = false;
|
||||
}
|
||||
$last = $db;
|
||||
}
|
||||
}
|
||||
if (!$row) {
|
||||
queries("DROP DATABASE " . idf_escape(DB));
|
||||
//! saved to history of removed database
|
||||
}
|
||||
queries_redirect(preg_replace('~db=[^&]*&~', '', ME) . "db=" . urlencode($_POST["name"]), lang('Database has been renamed.'), !$row);
|
||||
queries_redirect(ME . "db=" . urlencode($last), lang('Database has been created.'), $success);
|
||||
}
|
||||
} else {
|
||||
// alter database
|
||||
|
@ -49,17 +40,16 @@ $collate = null;
|
|||
if ($_POST) {
|
||||
$name = $_POST["name"];
|
||||
$collate = $_POST["collation"];
|
||||
} elseif (DB == "") {
|
||||
} elseif (DB != "") {
|
||||
$collate = db_collation(DB, $collations);
|
||||
} elseif ($driver == "sql") {
|
||||
// propose database name with limited privileges
|
||||
$result = $connection->query("SHOW GRANTS");
|
||||
while ($row = $result->fetch_row()) {
|
||||
if (preg_match('~ ON (`(([^\\\\`]|``|\\\\.)*)%`\\.\\*)?~', $row[0], $match) && $match[1]) {
|
||||
$name = stripcslashes(idf_unescape($match[2]));
|
||||
foreach (get_vals("SHOW GRANTS") as $grant) {
|
||||
if (preg_match('~ ON (`(([^\\\\`]|``|\\\\.)*)%`\\.\\*)?~', $grant, $match) && $match[1]) {
|
||||
$name = stripcslashes(idf_unescape("`$match[2]`"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$collate = db_collation(DB, $collations);
|
||||
}
|
||||
?>
|
||||
|
||||
|
|
|
@ -4,18 +4,15 @@ $tables_views = array_merge((array) $_POST["tables"], (array) $_POST["views"]);
|
|||
if ($tables_views && !$error && !$_POST["search"]) {
|
||||
$result = true;
|
||||
$message = "";
|
||||
if (count($_POST["tables"]) > 1 && ($_POST["drop"] || $_POST["truncate"])) {
|
||||
if ($driver == "sql" && count($_POST["tables"]) > 1 && ($_POST["drop"] || $_POST["truncate"])) {
|
||||
queries("SET foreign_key_checks = 0"); // allows to truncate or drop several tables at once
|
||||
}
|
||||
if (isset($_POST["truncate"])) {
|
||||
foreach ((array) $_POST["tables"] as $table) {
|
||||
if (!queries("TRUNCATE " . idf_escape($table))) {
|
||||
$result = false;
|
||||
break;
|
||||
}
|
||||
if ($_POST["truncate"]) {
|
||||
if ($_POST["tables"]) {
|
||||
$result = truncate_tables($_POST["tables"]);
|
||||
}
|
||||
$message = lang('Tables have been truncated.');
|
||||
} elseif (isset($_POST["move"])) {
|
||||
} elseif ($_POST["move"]) {
|
||||
$rename = array();
|
||||
foreach ($tables_views as $table) {
|
||||
$rename[] = idf_escape($table) . " TO " . idf_escape($_POST["target"]) . "." . idf_escape($table);
|
||||
|
@ -23,66 +20,65 @@ if ($tables_views && !$error && !$_POST["search"]) {
|
|||
$result = queries("RENAME TABLE " . implode(", ", $rename));
|
||||
//! move triggers
|
||||
$message = lang('Tables have been moved.');
|
||||
} elseif ((!isset($_POST["drop"]) || !$_POST["views"] || queries("DROP VIEW " . implode(", ", array_map('idf_escape', $_POST["views"]))))
|
||||
&& (!$_POST["tables"] || ($result = queries((isset($_POST["optimize"]) ? "OPTIMIZE" : (isset($_POST["check"]) ? "CHECK" : (isset($_POST["repair"]) ? "REPAIR" : (isset($_POST["drop"]) ? "DROP" : "ANALYZE")))) . " TABLE " . implode(", ", array_map('idf_escape', $_POST["tables"])))))
|
||||
) {
|
||||
if (isset($_POST["drop"])) {
|
||||
$message = lang('Tables have been dropped.');
|
||||
} else {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$message .= h("$row[Table]: $row[Msg_text]") . "<br>";
|
||||
}
|
||||
} elseif ($_POST["drop"]) {
|
||||
if ($_POST["views"]) {
|
||||
$result = drop_views($_POST["views"]);
|
||||
}
|
||||
if ($result && $_POST["tables"]) {
|
||||
$result = drop_tables($_POST["tables"]);
|
||||
}
|
||||
$message = lang('Tables have been dropped.');
|
||||
} elseif ($_POST["tables"] && ($result = queries(($_POST["optimize"] ? "OPTIMIZE" : ($_POST["check"] ? "CHECK" : ($_POST["repair"] ? "REPAIR" : "ANALYZE"))) . " TABLE " . implode(", ", array_map('idf_escape', $_POST["tables"]))))) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$message .= h("$row[Table]: $row[Msg_text]") . "<br>";
|
||||
}
|
||||
}
|
||||
queries_redirect(substr(ME, 0, -1), $message, $result);
|
||||
}
|
||||
|
||||
page_header(lang('Database') . ": " . h(DB), $error, false);
|
||||
page_header(lang('Database') . ": " . h(DB), $error, true);
|
||||
echo '<p><a href="' . h(ME) . 'database=">' . lang('Alter database') . "</a>\n";
|
||||
echo '<a href="' . h(ME) . 'schema=">' . lang('Database schema') . "</a>\n";
|
||||
$sums = array("Data_length" => 0, "Index_length" => 0, "Data_free" => 0);
|
||||
|
||||
echo "<h3>" . lang('Tables and views') . "</h3>\n";
|
||||
$table_status = table_status();
|
||||
if (!$table_status) {
|
||||
$tables_list = tables_list();
|
||||
if (!$tables_list) {
|
||||
echo "<p class='message'>" . lang('No tables.') . "\n";
|
||||
} else {
|
||||
echo "<form action='' method='post'>\n";
|
||||
echo "<p><input name='query' value='" . h($_POST["query"]) . "'> <input type='submit' name='search' value='" . lang('Search') . "'>\n";
|
||||
if ($_POST["search"] && $_POST["query"] != "") {
|
||||
$_GET["where"][0]["op"] = "LIKE";
|
||||
$_GET["where"][0]["val"] = "%$_POST[query]%";
|
||||
$_GET["where"][0]["op"] = "LIKE %%";
|
||||
$_GET["where"][0]["val"] = $_POST["query"];
|
||||
search_tables();
|
||||
}
|
||||
echo "<table cellspacing='0' class='nowrap' onclick='tableClick(event);'>\n";
|
||||
echo '<thead><tr class="wrap"><td><input id="check-all" type="checkbox" onclick="formCheck(this, /^(tables|views)\[/);"><th>' . lang('Table') . '<td>' . lang('Engine') . '<td>' . lang('Collation') . '<td>' . lang('Data Length') . '<td>' . lang('Index Length') . '<td>' . lang('Data Free') . '<td>' . lang('Auto Increment') . '<td>' . lang('Rows') . '<td>' . lang('Comment') . "</thead>\n";
|
||||
$sums = array();
|
||||
foreach ($table_status as $row) {
|
||||
$name = $row["Name"];
|
||||
echo '<tr' . odd() . '><td>' . checkbox((isset($row["Rows"]) ? "tables[]" : "views[]"), $name, in_array($name, $tables_views, true), "", "formUncheck('check-all');");
|
||||
echo '<thead><tr class="wrap"><td><input id="check-all" type="checkbox" onclick="formCheck(this, /^(tables|views)\[/);"><th>' . lang('Table') . '<td>' . lang('Engine') . '<td>' . lang('Collation') . '<td>' . lang('Data Length') . '<td>' . lang('Index Length') . '<td>' . lang('Data Free') . '<td>' . lang('Auto Increment') . '<td>' . lang('Rows') . (support("comment") ? '<td>' . lang('Comment') : '') . "</thead>\n";
|
||||
foreach ($tables_list as $name => $type) {
|
||||
$view = (isset($type) && !eregi("table", $type));
|
||||
echo '<tr' . odd() . '><td>' . checkbox(($view ? "views[]" : "tables[]"), $name, in_array($name, $tables_views, true), "", "formUncheck('check-all');");
|
||||
echo '<th><a href="' . h(ME) . 'table=' . urlencode($name) . '">' . h($name) . '</a>';
|
||||
if (isset($row["Rows"])) {
|
||||
echo "<td>$row[Engine]<td>$row[Collation]";
|
||||
foreach (array("Data_length" => "create", "Index_length" => "indexes", "Data_free" => "edit", "Auto_increment" => "auto_increment=1&create", "Rows" => "select") as $key => $link) {
|
||||
$val = number_format($row[$key], 0, '.', lang(','));
|
||||
echo '<td align="right">' . ($row[$key] != "" ? '<a href="' . h(ME . "$link=") . urlencode($name) . '">' . str_replace(" ", " ", ($key == "Rows" && $row["Engine"] == "InnoDB" && $val ? lang('~ %s', $val) : $val)) . '</a>' : ' ');
|
||||
$sums[$link] += ($row["Engine"] != "InnoDB" || $link != "edit" ? $row[$key] : 0);
|
||||
}
|
||||
echo "<td>" . nbsp($row["Comment"]);
|
||||
} else {
|
||||
if ($view) {
|
||||
echo '<td colspan="6"><a href="' . h(ME) . "view=" . urlencode($name) . '">' . lang('View') . '</a>';
|
||||
echo '<td align="right"><a href="' . h(ME) . "select=" . urlencode($name) . '">?</a>';
|
||||
echo '<td> ';
|
||||
} else {
|
||||
echo "<td id='Engine-" . h($name) . "'> <td id='Collation-" . h($name) . "'> ";
|
||||
foreach (array("Data_length" => "create", "Index_length" => "indexes", "Data_free" => "edit", "Auto_increment" => "auto_increment=1&create", "Rows" => "select") as $key => $link) {
|
||||
echo "<td align='right'><a href='" . h(ME . "$link=") . urlencode($name) . "' id='$key-" . h($name) . "'>?</a>";
|
||||
}
|
||||
}
|
||||
echo (support("comment") ? "<td id='Comment-" . h($name) . "'> " : "");
|
||||
}
|
||||
echo "<tr><td> <th>" . lang('%d in total', count($table_status));
|
||||
echo "<td>" . $connection->result($connection->query("SELECT @@storage_engine"));
|
||||
echo "<tr><td> <th>" . lang('%d in total', count($tables_list));
|
||||
echo "<td>" . $connection->result("SELECT @@storage_engine");
|
||||
echo "<td>" . db_collation(DB, collations());
|
||||
foreach (array("create", "indexes", "edit") as $val) {
|
||||
echo "<td align='right'>" . number_format($sums[$val], 0, '.', lang(','));
|
||||
foreach ($sums as $key => $val) {
|
||||
echo "<td align='right' id='sum-$key'> ";
|
||||
}
|
||||
echo "</table>\n";
|
||||
if (!information_schema(DB)) {
|
||||
echo "<p><input type='hidden' name='token' value='$token'><input type='submit' value='" . lang('Analyze') . "'> <input type='submit' name='optimize' value='" . lang('Optimize') . "'> <input type='submit' name='check' value='" . lang('Check') . "'> <input type='submit' name='repair' value='" . lang('Repair') . "'> <input type='submit' name='truncate' value='" . lang('Truncate') . "' onclick=\"return confirm('" . lang('Are you sure?') . " (' + formChecked(this, /tables/) + ')');\"> <input type='submit' name='drop' value='" . lang('Drop') . "' onclick=\"return confirm('" . lang('Are you sure?') . " (' + formChecked(this, /tables|views/) + ')');\">\n";
|
||||
echo "<p><input type='hidden' name='token' value='$token'>" . ($driver == "sql" ? "<input type='submit' value='" . lang('Analyze') . "'> <input type='submit' name='optimize' value='" . lang('Optimize') . "'> <input type='submit' name='check' value='" . lang('Check') . "'> <input type='submit' name='repair' value='" . lang('Repair') . "'> " : "") . "<input type='submit' name='truncate' value='" . lang('Truncate') . "' onclick=\"return confirm('" . lang('Are you sure?') . " (' + formChecked(this, /tables/) + ')');\"> <input type='submit' name='drop' value='" . lang('Drop') . "' onclick=\"return confirm('" . lang('Are you sure?') . " (' + formChecked(this, /tables|views/) + ')');\">\n";
|
||||
$dbs = get_databases();
|
||||
if (count($dbs) != 1) {
|
||||
$db = (isset($_POST["target"]) ? $_POST["target"] : DB);
|
||||
|
@ -93,8 +89,10 @@ if (!$table_status) {
|
|||
}
|
||||
|
||||
echo '<p><a href="' . h(ME) . 'create=">' . lang('Create table') . "</a>\n";
|
||||
if ($connection->server_info >= 5) {
|
||||
if (support("view")) {
|
||||
echo '<a href="' . h(ME) . 'view=">' . lang('Create view') . "</a>\n";
|
||||
}
|
||||
if (support("routine")) {
|
||||
echo "<h3>" . lang('Routines') . "</h3>\n";
|
||||
$result = $connection->query("SELECT * FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = " . $connection->quote(DB));
|
||||
if ($result->num_rows) {
|
||||
|
@ -110,9 +108,10 @@ if ($connection->server_info >= 5) {
|
|||
echo '<p><a href="' . h(ME) . 'procedure=">' . lang('Create procedure') . '</a> <a href="' . h(ME) . 'function=">' . lang('Create function') . "</a>\n";
|
||||
}
|
||||
|
||||
if ($connection->server_info >= 5.1 && ($result = $connection->query("SHOW EVENTS"))) {
|
||||
if (support("event")) {
|
||||
echo "<h3>" . lang('Events') . "</h3>\n";
|
||||
if ($result->num_rows) {
|
||||
$result = $connection->query("SHOW EVENTS");
|
||||
if ($result && $result->num_rows) {
|
||||
echo "<table cellspacing='0'>\n";
|
||||
echo "<thead><tr><th>" . lang('Name') . "<td>" . lang('Schedule') . "<td>" . lang('Start') . "<td>" . lang('End') . "</thead>\n";
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
|
@ -125,3 +124,34 @@ if ($connection->server_info >= 5.1 && ($result = $connection->query("SHOW EVENT
|
|||
}
|
||||
echo '<p><a href="' . h(ME) . 'event=">' . lang('Create event') . "</a>\n";
|
||||
}
|
||||
|
||||
page_footer();
|
||||
$table_status = table_status();
|
||||
if ($table_status) {
|
||||
echo "<script type='text/javascript'>\n";
|
||||
foreach ($table_status as $row) {
|
||||
$id = addcslashes($row["Name"], "\\'/");
|
||||
echo "setHtml('Comment-$id', '" . nbsp($row["Comment"]) . "');\n";
|
||||
if (!eregi("view", $row["Engine"])) {
|
||||
foreach (array("Engine", "Collation") as $key) {
|
||||
echo "setHtml('$key-$id', '" . nbsp($row[$key]) . "');\n";
|
||||
}
|
||||
foreach ($sums + array("Auto_increment" => 0, "Rows" => 0) as $key => $val) {
|
||||
if ($row[$key] != "") {
|
||||
$val = number_format($row[$key], 0, '.', lang(','));
|
||||
echo "setHtml('$key-$id', '" . ($key == "Rows" && $row["Engine"] == "InnoDB" && $val ? "~ $val" : $val) . "');\n";
|
||||
if (isset($sums[$key])) {
|
||||
$sums[$key] += ($row["Engine"] != "InnoDB" || $key != "Data_free" ? $row[$key] : 0);
|
||||
}
|
||||
} elseif (array_key_exists($key, $row)) {
|
||||
echo "setHtml('$key-$id');\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($sums as $key => $val) {
|
||||
echo "setHtml('sum-$key', '" . number_format($val, 0, '.', lang(',')) . "');\n";
|
||||
}
|
||||
echo "</script>\n";
|
||||
}
|
||||
exit; // page_footer() already called
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
$TABLE = $_GET["download"];
|
||||
header("Content-Type: application/octet-stream");
|
||||
header("Content-Disposition: attachment; filename=" . friendly_url("$TABLE-" . implode("_", $_GET["where"])) . "." . friendly_url($_GET["field"]));
|
||||
echo $connection->result($connection->query("SELECT " . idf_escape($_GET["field"]) . " FROM " . idf_escape($TABLE) . " WHERE " . where($_GET) . " LIMIT 1"));
|
||||
echo $connection->result("SELECT" . limit(idf_escape($_GET["field"]) . " FROM " . idf_escape($TABLE) . " WHERE " . where($_GET), 1));
|
||||
exit; // don't output footer
|
||||
|
|
406
adminer/drivers/mssql.inc.php
Normal file
406
adminer/drivers/mssql.inc.php
Normal file
|
@ -0,0 +1,406 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Jakub Cernohuby
|
||||
* @author Vladimir Stastka
|
||||
* @author Jakub Vrana
|
||||
*/
|
||||
|
||||
$possible_drivers[] = "SQLSRV";
|
||||
$possible_drivers[] = "MSSQL";
|
||||
if (extension_loaded("sqlsrv") || extension_loaded("mssql")) {
|
||||
$drivers["mssql"] = "MS SQL";
|
||||
}
|
||||
|
||||
if (isset($_GET["mssql"])) {
|
||||
define("DRIVER", "mssql");
|
||||
if (extension_loaded("sqlsrv")) {
|
||||
class Min_DB {
|
||||
var $extension = "sqlsrv", $_link, $_result, $server_info, $affected_rows, $error;
|
||||
|
||||
function _get_error() {
|
||||
$this->error = "";
|
||||
foreach (sqlsrv_errors() as $error) {
|
||||
$this->error .= "$error[message]\n";
|
||||
}
|
||||
$this->error = rtrim($this->error);
|
||||
}
|
||||
|
||||
function connect($server, $username, $password) {
|
||||
$this->_link = @sqlsrv_connect($server, array("UID" => $username, "PWD" => $password));
|
||||
if ($this->_link) {
|
||||
$info = sqlsrv_server_info($this->_link);
|
||||
$this->server_info = $info['SQLServerVersion'];
|
||||
} else {
|
||||
$this->_get_error();
|
||||
}
|
||||
return (bool) $this->_link;
|
||||
}
|
||||
|
||||
function quote($string) {
|
||||
return "'" . str_replace("'", "''", $string) . "'";
|
||||
}
|
||||
|
||||
function select_db($database) {
|
||||
return $this->query("USE $database");
|
||||
}
|
||||
|
||||
|
||||
function query($query, $unbuffered = false) {
|
||||
$result = sqlsrv_query($this->_link, $query); //! , array(), ($unbuffered ? array() : array("Scrollable" => "keyset"))
|
||||
if (!$result) {
|
||||
$this->_get_error();
|
||||
return false;
|
||||
}
|
||||
return $this->store_result($result);
|
||||
}
|
||||
|
||||
function multi_query($query) {
|
||||
$this->_result = sqlsrv_query($this->_link, $query);
|
||||
if (!$this->_result) {
|
||||
$this->_get_error();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function store_result($result = null) {
|
||||
if (!$result) {
|
||||
$result = $this->_result;
|
||||
}
|
||||
if (sqlsrv_field_metadata($result)) {
|
||||
return new Min_Result($result);
|
||||
}
|
||||
$this->affected_rows = sqlsrv_rows_affected($result);
|
||||
return true;
|
||||
}
|
||||
|
||||
function next_result() {
|
||||
return sqlsrv_next_result($this->_result);
|
||||
}
|
||||
|
||||
function result($query, $field = 0) {
|
||||
$result = $this->query($query);
|
||||
if (!is_object($result)) {
|
||||
return false;
|
||||
}
|
||||
$row = $result->fetch_row();
|
||||
return $row[$field];
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
var $_result, $_offset = 0, $_fields, $num_rows;
|
||||
|
||||
function Min_Result($result) {
|
||||
$this->_result = $result;
|
||||
$this->num_rows = sqlsrv_has_rows($result); //! sqlsrv_num_rows($result)
|
||||
}
|
||||
|
||||
function _convert($row) {
|
||||
foreach ((array) $row as $key => $val) {
|
||||
if (is_a($val, 'DateTime')) {
|
||||
$row[$key] = $val->format("Y-m-d H:i:s");
|
||||
}
|
||||
//! stream
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
|
||||
function fetch_assoc() {
|
||||
return $this->_convert(sqlsrv_fetch_array($this->_result, SQLSRV_FETCH_ASSOC, SQLSRV_SCROLL_NEXT));
|
||||
}
|
||||
|
||||
function fetch_row() {
|
||||
return $this->_convert(sqlsrv_fetch_array($this->_result, SQLSRV_FETCH_NUMERIC, SQLSRV_SCROLL_NEXT));
|
||||
}
|
||||
|
||||
function fetch_field() {
|
||||
if (!$this->_fields) {
|
||||
$this->_fields = sqlsrv_field_metadata($this->_result);
|
||||
}
|
||||
$field = $this->_fields[$this->_offset++];
|
||||
$return = new stdClass;
|
||||
$return->name = $field["Name"];
|
||||
$return->orgname = $field["Name"];
|
||||
$return->type = ($field["Type"] == 1 ? 254 : 0);
|
||||
return $return;
|
||||
}
|
||||
|
||||
function __destruct() {
|
||||
sqlsrv_free_stmt($this->_result);
|
||||
}
|
||||
}
|
||||
|
||||
} elseif (extension_loaded("mssql")) {
|
||||
class Min_DB {
|
||||
var $extension = "MSSQL", $_link, $_result, $server_info, $affected_rows, $error;
|
||||
|
||||
function connect($server, $username, $password) {
|
||||
$this->_link = @mssql_connect($server, $username, $password);
|
||||
if ($this->_link) {
|
||||
$result = $this->query("SELECT SERVERPROPERTY('ProductLevel'), SERVERPROPERTY('Edition')");
|
||||
$row = $result->fetch_row();
|
||||
$this->server_info = $this->result("sp_server_info 2", 2)." [$row[0]] $row[1]";
|
||||
} else {
|
||||
$this->error = mssql_get_last_message();
|
||||
}
|
||||
return (bool) $this->_link;
|
||||
}
|
||||
|
||||
function quote($string) {
|
||||
return "'" . str_replace("'", "''", $string) . "'";
|
||||
}
|
||||
|
||||
function select_db($database) {
|
||||
return mssql_select_db($database);
|
||||
}
|
||||
|
||||
function query($query, $unbuffered = false) {
|
||||
$result = mssql_query($query, $this->_link); //! $unbuffered
|
||||
if (!$result) {
|
||||
$this->error = mssql_get_last_message();
|
||||
return false;
|
||||
}
|
||||
if ($result === true) {
|
||||
$this->affected_rows = mssql_rows_affected($this->_link);
|
||||
return true;
|
||||
}
|
||||
return new Min_Result($result);
|
||||
}
|
||||
|
||||
function multi_query($query) {
|
||||
return $this->_result = $this->query($query);
|
||||
}
|
||||
|
||||
function store_result() {
|
||||
return $this->_result;
|
||||
}
|
||||
|
||||
function next_result() {
|
||||
return mssql_next_result($this->_result);
|
||||
}
|
||||
|
||||
function result($query, $field = 0) {
|
||||
$result = $this->query($query);
|
||||
if (!is_object($result)) {
|
||||
return false;
|
||||
}
|
||||
return mssql_result($result->_result, 0, $field);
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
var $_result, $_offset = 0, $_fields, $num_rows;
|
||||
|
||||
function Min_Result($result) {
|
||||
$this->_result = $result;
|
||||
$this->num_rows = mssql_num_rows($result);
|
||||
}
|
||||
|
||||
function fetch_assoc() {
|
||||
return mssql_fetch_assoc($this->_result);
|
||||
}
|
||||
|
||||
function fetch_row() {
|
||||
return mssql_fetch_row($this->_result);
|
||||
}
|
||||
|
||||
function num_rows() {
|
||||
return mssql_num_rows($this->_result);
|
||||
}
|
||||
|
||||
function fetch_field() {
|
||||
$return = mssql_fetch_field($this->_result);
|
||||
$return->orgtable = $return->table;
|
||||
$return->orgname = $return->name;
|
||||
return $return;
|
||||
}
|
||||
|
||||
function __destruct() {
|
||||
mssql_free_result($this->_result);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function idf_escape($idf) {
|
||||
return "[" . str_replace("]", "]]", $idf) . "]";
|
||||
}
|
||||
|
||||
function connect() {
|
||||
global $adminer;
|
||||
$connection = new Min_DB;
|
||||
$credentials = $adminer->credentials();
|
||||
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
|
||||
return $connection;
|
||||
}
|
||||
return $connection->error;
|
||||
}
|
||||
|
||||
function get_databases() {
|
||||
return get_vals("EXEC sp_databases");
|
||||
}
|
||||
|
||||
function limit($query, $limit, $offset = 0) {
|
||||
return (isset($limit) ? " TOP ($limit)" : "") . " $query"; //! offset
|
||||
}
|
||||
|
||||
function limit1($query, $limit, $offset = 0) {
|
||||
return limit($query, 1);
|
||||
}
|
||||
|
||||
function db_collation($db, $collations) {
|
||||
global $connection;
|
||||
return $connection->result("SELECT collation_name FROM sys.databases WHERE name = " . $connection->quote($db));
|
||||
}
|
||||
|
||||
function engines() {
|
||||
return array();
|
||||
}
|
||||
|
||||
function logged_user() {
|
||||
global $connection;
|
||||
return $connection->result("SELECT SUSER_NAME()");
|
||||
}
|
||||
|
||||
function tables_list() {
|
||||
return get_key_vals("SELECT TABLE_NAME, TABLE_TYPE FROM information_schema.TABLES");
|
||||
}
|
||||
|
||||
function count_tables($databases) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
foreach ($databases as $db) {
|
||||
$connection->select_db($db);
|
||||
$return[$db] = $connection->result("SELECT COUNT(*) FROM information_schema.TABLES");
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function table_status($name = "") {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SELECT TABLE_NAME AS Name, TABLE_TYPE AS Engine FROM information_schema.TABLES" . ($name != "" ? " WHERE TABLE_NAME = " . $connection->quote($name) : ""));
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
if ($name != "") {
|
||||
return $row;
|
||||
}
|
||||
$return[$row["Name"]] = $row;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function fk_support($table_status) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function fields($table) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SELECT * FROM information_schema.COLUMNS WHERE TABLE_NAME = " . $connection->quote($table));
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["COLUMN_NAME"]] = array(
|
||||
"field" => $row["COLUMN_NAME"],
|
||||
"full_type" => $row["DATA_TYPE"],
|
||||
"type" => $row["DATA_TYPE"],
|
||||
"length" => $row["CHARACTER_MAXIMUM_LENGTH"], //! NUMERIC_, DATETIME_?
|
||||
"default" => $row["COLUMN_DEFAULT"],
|
||||
"null" => ($row["IS_NULLABLE"] == "YES"),
|
||||
"collation" => $row["COLLATION_NAME"],
|
||||
"privileges" => array("insert" => 1, "select" => 1, "update" => 1),
|
||||
//! primary - is_identity in sys.columns
|
||||
);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function indexes($table, $connection2 = null) {
|
||||
global $connection;
|
||||
if (!is_object($connection2)) {
|
||||
$connection2 = $connection;
|
||||
}
|
||||
$return = array();
|
||||
// sp_statistics doesn't return information about primary key
|
||||
$result = $connection2->query("SELECT indexes.name, key_ordinal, is_unique, is_primary_key, columns.name AS column_name
|
||||
FROM sys.indexes
|
||||
INNER JOIN sys.index_columns ON indexes.object_id = index_columns.object_id AND indexes.index_id = index_columns.index_id
|
||||
INNER JOIN sys.columns ON index_columns.object_id = columns.object_id AND index_columns.column_id = columns.column_id
|
||||
WHERE OBJECT_NAME(indexes.object_id) = " . $connection2->quote($table));
|
||||
if ($result) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["name"]]["type"] = ($row["is_primary_key"] ? "PRIMARY" : ($row["is_unique"] ? "UNIQUE" : "INDEX"));
|
||||
$return[$row["name"]]["columns"][$row["key_ordinal"]] = $row["column_name"];
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function collations() {
|
||||
$return = array();
|
||||
foreach (get_vals("SELECT name FROM fn_helpcollations()") as $collation) {
|
||||
$return[ereg_replace("_.*", "", $collation)][] = $collation;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function information_schema($db) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function error() {
|
||||
global $connection;
|
||||
return nl_br(h(ereg_replace("^(\\[[^]]*])+", "", $connection->error)));
|
||||
}
|
||||
|
||||
function exact_value($val) {
|
||||
global $connection;
|
||||
return $connection->quote($val);
|
||||
}
|
||||
|
||||
function rename_database($name, $collation) {
|
||||
if ($collation) {
|
||||
queries("ALTER DATABASE " . idf_escape(DB) . " COLLATE " . idf_escape($collation));
|
||||
}
|
||||
return queries("ALTER DATABASE " . idf_escape(DB) . " MODIFY NAME = " . idf_escape($name)); //! false negative "The database name 'test2' has been set."
|
||||
}
|
||||
|
||||
function auto_increment() {
|
||||
return " IDENTITY";
|
||||
}
|
||||
|
||||
function explain($connection, $query) {
|
||||
$connection->query("SET SHOWPLAN_ALL ON");
|
||||
$return = $connection->query($query);
|
||||
$connection->query("SET SHOWPLAN_ALL OFF"); // connection is used also for indexes
|
||||
return $return;
|
||||
}
|
||||
|
||||
function support($feature) {
|
||||
return ereg('^(view|routine|trigger)$', $feature);
|
||||
}
|
||||
|
||||
$driver = "mssql";
|
||||
$types = array();
|
||||
$structured_types = array();
|
||||
foreach (array(
|
||||
lang('Numbers') => array("tinyint" => 3, "smallint" => 5, "int" => 10, "bigint" => 20, "bit" => 1, "decimal" => 0, "real" => 12, "float" => 53, "smallmoney" => 10, "money" => 20),
|
||||
lang('Date and time') => array("date" => 10, "smalldatetime" => 19, "datetime" => 19, "datetime2" => 19, "time" => 8, "datetimeoffset" => 10),
|
||||
lang('Strings') => array("char" => 8000, "varchar" => 8000, "text" => 2147483647, "nchar" => 4000, "nvarchar" => 4000, "ntext" => 1073741823),
|
||||
lang('Binary') => array("binary" => 8000, "varbinary" => 8000, "image" => 2147483647),
|
||||
) as $key => $val) {
|
||||
$types += $val;
|
||||
$structured_types[$key] = array_keys($val);
|
||||
}
|
||||
$unsigned = array();
|
||||
$operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL");
|
||||
$functions = array("len", "lower", "round", "upper");
|
||||
$grouping = array("avg", "count", "count distinct", "max", "min", "sum");
|
||||
$edit_functions = array(
|
||||
array(
|
||||
"date|time" => "getdate",
|
||||
), array(
|
||||
"int|decimal|real|float|money|datetime" => "+/-",
|
||||
"char|text" => "+",
|
||||
)
|
||||
);
|
||||
}
|
713
adminer/drivers/mysql.inc.php
Normal file
713
adminer/drivers/mysql.inc.php
Normal file
|
@ -0,0 +1,713 @@
|
|||
<?php
|
||||
$possible_drivers[] = "MySQLi";
|
||||
$possible_drivers[] = "MySQL";
|
||||
$possible_drivers[] = "PDO_MySQL";
|
||||
if (extension_loaded("mysqli") || extension_loaded("mysql") || extension_loaded("pdo_mysql")) {
|
||||
$drivers = array("server" => "MySQL") + $drivers;
|
||||
}
|
||||
|
||||
if (!defined("DRIVER")) {
|
||||
define("DRIVER", "server"); // server - backwards compatibility
|
||||
// MySQLi supports everything, MySQL doesn't support multiple result sets, PDO_MySQL doesn't support orgtable
|
||||
if (extension_loaded("mysqli")) {
|
||||
class Min_DB extends MySQLi {
|
||||
var $extension = "MySQLi";
|
||||
|
||||
function Min_DB() {
|
||||
parent::init();
|
||||
}
|
||||
|
||||
function connect($server, $username, $password) {
|
||||
list($host, $port) = explode(":", $server, 2); // part after : is used for port or socket
|
||||
return @$this->real_connect(
|
||||
($server != "" ? $host : ini_get("mysqli.default_host")),
|
||||
("$server$username" != "" ? $username : ini_get("mysqli.default_user")),
|
||||
("$server$username$password" != "" ? $password : ini_get("mysqli.default_pw")),
|
||||
null,
|
||||
(is_numeric($port) ? $port : ini_get("mysqli.default_port")),
|
||||
(!is_numeric($port) ? $port : null)
|
||||
);
|
||||
}
|
||||
|
||||
function result($query, $field = 0) {
|
||||
$result = $this->query($query);
|
||||
if (!$result) {
|
||||
return false;
|
||||
}
|
||||
$row = $result->fetch_array();
|
||||
return $row[$field];
|
||||
}
|
||||
|
||||
function quote($string) {
|
||||
return "'" . $this->escape_string($string) . "'";
|
||||
}
|
||||
}
|
||||
|
||||
} elseif (extension_loaded("mysql")) {
|
||||
class Min_DB {
|
||||
var
|
||||
$extension = "MySQL", ///< @var string extension name
|
||||
$server_info, ///< @var string server version
|
||||
$affected_rows, ///< @var int number of affected rows
|
||||
$error, ///< @var string last error message
|
||||
$_link, $_result ///< @access private
|
||||
;
|
||||
|
||||
/** Connect to server
|
||||
* @param string
|
||||
* @param string
|
||||
* @param string
|
||||
* @return bool
|
||||
*/
|
||||
function connect($server, $username, $password) {
|
||||
$this->_link = @mysql_connect(
|
||||
($server != "" ? $server : ini_get("mysql.default_host")),
|
||||
("$server$username" != "" ? $username : ini_get("mysql.default_user")),
|
||||
("$server$username$password" != "" ? $password : ini_get("mysql.default_password")),
|
||||
true,
|
||||
131072 // CLIENT_MULTI_RESULTS for CALL
|
||||
);
|
||||
if ($this->_link) {
|
||||
$this->server_info = mysql_get_server_info($this->_link);
|
||||
} else {
|
||||
$this->error = mysql_error();
|
||||
}
|
||||
return (bool) $this->_link;
|
||||
}
|
||||
|
||||
/** Quote string to use in SQL
|
||||
* @param string
|
||||
* @return string escaped string enclosed in '
|
||||
*/
|
||||
function quote($string) {
|
||||
return "'" . mysql_real_escape_string($string, $this->_link) . "'";
|
||||
}
|
||||
|
||||
/** Select database
|
||||
* @param string
|
||||
* @return bool
|
||||
*/
|
||||
function select_db($database) {
|
||||
return mysql_select_db($database, $this->_link);
|
||||
}
|
||||
|
||||
/** Send query
|
||||
* @param string
|
||||
* @param bool
|
||||
* @return mixed bool or Min_Result
|
||||
*/
|
||||
function query($query, $unbuffered = false) {
|
||||
$result = @($unbuffered ? mysql_unbuffered_query($query, $this->_link) : mysql_query($query, $this->_link)); // @ - mute mysql.trace_mode
|
||||
if (!$result) {
|
||||
$this->error = mysql_error($this->_link);
|
||||
return false;
|
||||
}
|
||||
if ($result === true) {
|
||||
$this->affected_rows = mysql_affected_rows($this->_link);
|
||||
$this->info = mysql_info($this->_link);
|
||||
return true;
|
||||
}
|
||||
return new Min_Result($result);
|
||||
}
|
||||
|
||||
/** Send query with more resultsets
|
||||
* @param string
|
||||
* @return bool
|
||||
*/
|
||||
function multi_query($query) {
|
||||
return $this->_result = $this->query($query);
|
||||
}
|
||||
|
||||
/** Get current resultset
|
||||
* @return Min_Result
|
||||
*/
|
||||
function store_result() {
|
||||
return $this->_result;
|
||||
}
|
||||
|
||||
/** Fetch next resultset
|
||||
* @return bool
|
||||
*/
|
||||
function next_result() {
|
||||
// MySQL extension doesn't support multiple results
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Get single field from result
|
||||
* @param string
|
||||
* @param int
|
||||
* @return string
|
||||
*/
|
||||
function result($query, $field = 0) {
|
||||
$result = $this->query($query);
|
||||
if (!$result) {
|
||||
return false;
|
||||
}
|
||||
return mysql_result($result->_result, 0, $field);
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
var
|
||||
$num_rows, ///< @var int number of rows in the result
|
||||
$_result ///< @access private
|
||||
;
|
||||
|
||||
/** Constructor
|
||||
* @param resource
|
||||
*/
|
||||
function Min_Result($result) {
|
||||
$this->_result = $result;
|
||||
$this->num_rows = mysql_num_rows($result);
|
||||
}
|
||||
|
||||
/** Fetch next row as associative array
|
||||
* @return array
|
||||
*/
|
||||
function fetch_assoc() {
|
||||
return mysql_fetch_assoc($this->_result);
|
||||
}
|
||||
|
||||
/** Fetch next row as numbered array
|
||||
* @return array
|
||||
*/
|
||||
function fetch_row() {
|
||||
return mysql_fetch_row($this->_result);
|
||||
}
|
||||
|
||||
/** Fetch next field
|
||||
* @return object properties: name, type, orgtable, orgname, charsetnr
|
||||
*/
|
||||
function fetch_field() {
|
||||
$return = mysql_fetch_field($this->_result);
|
||||
$return->orgtable = $return->table;
|
||||
$return->orgname = $return->name;
|
||||
$return->charsetnr = ($return->blob ? 63 : 0);
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Free result set
|
||||
*/
|
||||
function __destruct() {
|
||||
mysql_free_result($this->_result); //! not called in PHP 4 which is a problem with mysql.trace_mode
|
||||
}
|
||||
}
|
||||
|
||||
} elseif (extension_loaded("pdo_mysql")) {
|
||||
class Min_DB extends Min_PDO {
|
||||
var $extension = "PDO_MySQL";
|
||||
|
||||
function connect($server, $username, $password) {
|
||||
$this->dsn("mysql:host=" . str_replace(":", ";unix_socket=", preg_replace('~:([0-9])~', ';port=\\1', $server)), $username, $password);
|
||||
return true;
|
||||
}
|
||||
|
||||
function select_db($database) {
|
||||
// database selection is separated from the connection so dbname in DSN can't be used
|
||||
return $this->query("USE " . idf_escape($database));
|
||||
}
|
||||
|
||||
function query($query, $unbuffered = false) {
|
||||
$this->setAttribute(1000, !$unbuffered); // 1000 - PDO::MYSQL_ATTR_USE_BUFFERED_QUERY
|
||||
return parent::query($query, $unbuffered);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Escape database identifier
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function idf_escape($idf) {
|
||||
return "`" . str_replace("`", "``", $idf) . "`";
|
||||
}
|
||||
|
||||
/** Connect to the database
|
||||
* @return mixed Min_DB or string for error
|
||||
*/
|
||||
function connect() {
|
||||
global $adminer;
|
||||
$connection = new Min_DB;
|
||||
$credentials = $adminer->credentials();
|
||||
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
|
||||
$connection->query("SET SQL_QUOTE_SHOW_CREATE=1");
|
||||
$connection->query("SET NAMES utf8");
|
||||
return $connection;
|
||||
}
|
||||
return $connection->error;
|
||||
}
|
||||
|
||||
/** Get cached list of databases
|
||||
* @param bool
|
||||
* @return array
|
||||
*/
|
||||
function get_databases($flush = true) {
|
||||
// SHOW DATABASES can take a very long time so it is cached
|
||||
$return = &get_session("databases");
|
||||
if (!isset($return)) {
|
||||
if ($flush) {
|
||||
restart_session();
|
||||
ob_flush();
|
||||
flush();
|
||||
}
|
||||
$return = get_vals("SHOW DATABASES");
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Formulate SQL query with limit
|
||||
* @param string everything after SELECT
|
||||
* @param int
|
||||
* @param int
|
||||
* @return string
|
||||
*/
|
||||
function limit($query, $limit, $offset = 0) {
|
||||
return " $query" . (isset($limit) ? "\nLIMIT $limit" . ($offset ? " OFFSET $offset" : "") : "");
|
||||
}
|
||||
|
||||
/** Formulate SQL modification query with limit 1
|
||||
* @param string everything after UPDATE or DELETE
|
||||
* @return string
|
||||
*/
|
||||
function limit1($query) {
|
||||
return limit($query, 1);
|
||||
}
|
||||
|
||||
/** Get database collation
|
||||
* @param string
|
||||
* @param array result of collations()
|
||||
* @return string
|
||||
*/
|
||||
function db_collation($db, $collations) {
|
||||
global $connection;
|
||||
$return = null;
|
||||
$create = $connection->result("SHOW CREATE DATABASE " . idf_escape($db), 1);
|
||||
if (preg_match('~ COLLATE ([^ ]+)~', $create, $match)) {
|
||||
$return = $match[1];
|
||||
} elseif (preg_match('~ CHARACTER SET ([^ ]+)~', $create, $match)) {
|
||||
// default collation
|
||||
$return = $collations[$match[1]][0];
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Get supported engines
|
||||
* @return array
|
||||
*/
|
||||
function engines() {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SHOW ENGINES");
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
if (ereg("YES|DEFAULT", $row["Support"])) {
|
||||
$return[] = $row["Engine"];
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Get logged user
|
||||
* @return string
|
||||
*/
|
||||
function logged_user() {
|
||||
global $connection;
|
||||
return $connection->result("SELECT USER()");
|
||||
}
|
||||
|
||||
/** Get tables list
|
||||
* @return array
|
||||
*/
|
||||
function tables_list() {
|
||||
global $connection;
|
||||
return get_key_vals("SHOW" . ($connection->server_info >= 5 ? " FULL" : "") . " TABLES");
|
||||
}
|
||||
|
||||
/** Count tables in all databases
|
||||
* @param array
|
||||
* @return array array($db => $tables)
|
||||
*/
|
||||
function count_tables($databases) {
|
||||
$return = array();
|
||||
foreach ($databases as $db) {
|
||||
$return[$db] = count(get_vals("SHOW TABLES IN " . idf_escape($db)));
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Get table status
|
||||
* @param string
|
||||
* @return array
|
||||
*/
|
||||
function table_status($name = "") {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SHOW TABLE STATUS" . ($name != "" ? " LIKE " . $connection->quote(addcslashes($name, "%_")) : ""));
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
if ($row["Engine"] == "InnoDB") {
|
||||
// ignore internal comment, unnecessary since MySQL 5.1.21
|
||||
$row["Comment"] = preg_replace('~(?:(.+); )?InnoDB free: .*~', '\\1', $row["Comment"]);
|
||||
}
|
||||
if (!isset($row["Rows"])) {
|
||||
$row["Engine"] = "VIEW";
|
||||
$row["Comment"] = "";
|
||||
}
|
||||
if ($name != "") {
|
||||
return $row;
|
||||
}
|
||||
$return[$row["Name"]] = $row;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Check if table supports foreign keys
|
||||
* @param array result of table_status
|
||||
* @return bool
|
||||
*/
|
||||
function fk_support($table_status) {
|
||||
return ($table_status["Engine"] == "InnoDB");
|
||||
}
|
||||
|
||||
/** Get information about fields
|
||||
* @param string
|
||||
* @return array array($name => array("field" => , "full_type" => , "type" => , "length" => , "unsigned" => , "default" => , "null" => , "auto_increment" => , "on_update" => , "collation" => , "privileges" => , "comment" => , "primary" => ))
|
||||
*/
|
||||
function fields($table) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SHOW FULL COLUMNS FROM " . idf_escape($table));
|
||||
if ($result) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
preg_match('~^([^( ]+)(?:\\((.+)\\))?( unsigned)?( zerofill)?$~', $row["Type"], $match);
|
||||
$return[$row["Field"]] = array(
|
||||
"field" => $row["Field"],
|
||||
"full_type" => $row["Type"],
|
||||
"type" => $match[1],
|
||||
"length" => $match[2],
|
||||
"unsigned" => ltrim($match[3] . $match[4]),
|
||||
"default" => ($row["Default"] != "" || ereg("char", $match[1]) ? $row["Default"] : null),
|
||||
"null" => ($row["Null"] == "YES"),
|
||||
"auto_increment" => ($row["Extra"] == "auto_increment"),
|
||||
"on_update" => (eregi('^on update (.+)', $row["Extra"], $match) ? $match[1] : ""), //! available since MySQL 5.1.23
|
||||
"collation" => $row["Collation"],
|
||||
"privileges" => array_flip(explode(",", $row["Privileges"])),
|
||||
"comment" => $row["Comment"],
|
||||
"primary" => ($row["Key"] == "PRI"),
|
||||
);
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Get table indexes
|
||||
* @param string
|
||||
* @param string Min_DB to use
|
||||
* @return array array($key_name => array("type" => , "columns" => array(), "lengths" => array()))
|
||||
*/
|
||||
function indexes($table, $connection2 = null) {
|
||||
global $connection;
|
||||
if (!is_object($connection2)) { // use the main connection if the separate connection is unavailable
|
||||
$connection2 = $connection;
|
||||
}
|
||||
$return = array();
|
||||
$result = $connection2->query("SHOW INDEX FROM " . idf_escape($table));
|
||||
if ($result) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["Key_name"]]["type"] = ($row["Key_name"] == "PRIMARY" ? "PRIMARY" : ($row["Index_type"] == "FULLTEXT" ? "FULLTEXT" : ($row["Non_unique"] ? "INDEX" : "UNIQUE")));
|
||||
$return[$row["Key_name"]]["columns"][] = $row["Column_name"];
|
||||
$return[$row["Key_name"]]["lengths"][] = $row["Sub_part"];
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Get foreign keys in table
|
||||
* @param string
|
||||
* @return array array($name => array("db" => , "table" => , "source" => array(), "target" => array(), "on_delete" => , "on_update" => ))
|
||||
*/
|
||||
function foreign_keys($table) {
|
||||
global $connection, $on_actions;
|
||||
static $pattern = '`(?:[^`]|``)+`';
|
||||
$return = array();
|
||||
$create_table = $connection->result("SHOW CREATE TABLE " . idf_escape($table), 1);
|
||||
if ($create_table) {
|
||||
preg_match_all("~CONSTRAINT ($pattern) FOREIGN KEY \\(((?:$pattern,? ?)+)\\) REFERENCES ($pattern)(?:\\.($pattern))? \\(((?:$pattern,? ?)+)\\)(?: ON DELETE (" . implode("|", $on_actions) . "))?(?: ON UPDATE (" . implode("|", $on_actions) . "))?~", $create_table, $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $match) {
|
||||
preg_match_all("~$pattern~", $match[2], $source);
|
||||
preg_match_all("~$pattern~", $match[5], $target);
|
||||
$return[idf_unescape($match[1])] = array(
|
||||
"db" => idf_unescape($match[4] != "" ? $match[3] : $match[4]),
|
||||
"table" => idf_unescape($match[4] != "" ? $match[4] : $match[3]),
|
||||
"source" => array_map('idf_unescape', $source[0]),
|
||||
"target" => array_map('idf_unescape', $target[0]),
|
||||
"on_delete" => $match[6],
|
||||
"on_update" => $match[7],
|
||||
);
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Get view SELECT
|
||||
* @param string
|
||||
* @return array array("select" => )
|
||||
*/
|
||||
function view($name) {
|
||||
global $connection;
|
||||
return array("select" => preg_replace('~^(?:[^`]|`[^`]*`)* AS ~U', '', $connection->result("SHOW CREATE VIEW " . idf_escape($name), 1)));
|
||||
}
|
||||
|
||||
/** Get sorted grouped list of collations
|
||||
* @return array
|
||||
*/
|
||||
function collations() {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SHOW COLLATION");
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["Charset"]][] = $row["Collation"];
|
||||
}
|
||||
ksort($return);
|
||||
foreach ($return as $key => $val) {
|
||||
sort($return[$key]);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Find out if database is information_schema
|
||||
* @param string
|
||||
* @return bool
|
||||
*/
|
||||
function information_schema($db) {
|
||||
global $connection;
|
||||
return ($connection->server_info >= 5 && $db == "information_schema");
|
||||
}
|
||||
|
||||
/** Get escaped error message
|
||||
* @return string
|
||||
*/
|
||||
function error() {
|
||||
global $connection;
|
||||
return h(preg_replace('~^You have an error.*syntax to use~U', "Syntax error", $connection->error));
|
||||
}
|
||||
|
||||
/** Return expression for binary comparison
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function exact_value($val) {
|
||||
global $connection;
|
||||
return "BINARY " . $connection->quote($val);
|
||||
}
|
||||
|
||||
/** Rename database from DB
|
||||
* @param string new name
|
||||
* @return string
|
||||
* @return bool
|
||||
*/
|
||||
function rename_database($name, $collation) {
|
||||
global $connection;
|
||||
$return = false;
|
||||
if (queries("CREATE DATABASE " . idf_escape($name) . ($collation ? " COLLATE " . $connection->quote($collation) : ""))) {
|
||||
//! move triggers
|
||||
$return = true; // table list may by empty
|
||||
foreach (tables_list() as $table) {
|
||||
if (!queries("RENAME TABLE " . idf_escape($table) . " TO " . idf_escape($name) . "." . idf_escape($table))) {
|
||||
$return = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($return) {
|
||||
queries("DROP DATABASE " . idf_escape(DB));
|
||||
//! saved to history of removed database
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Generate modifier for auto increment column
|
||||
* @return string
|
||||
*/
|
||||
function auto_increment() {
|
||||
$auto_increment_index = " PRIMARY KEY";
|
||||
// don't overwrite primary key by auto_increment
|
||||
if ($_GET["create"] != "" && $_POST["auto_increment_col"]) {
|
||||
foreach (indexes($_GET["create"]) as $index) {
|
||||
if (in_array($_POST["fields"][$_POST["auto_increment_col"]]["orig"], $index["columns"], true)) {
|
||||
$auto_increment_index = "";
|
||||
break;
|
||||
}
|
||||
if ($index["type"] == "PRIMARY") {
|
||||
$auto_increment_index = " UNIQUE";
|
||||
}
|
||||
}
|
||||
}
|
||||
return " AUTO_INCREMENT$auto_increment_index";
|
||||
}
|
||||
|
||||
/** Run commands to create or alter table
|
||||
* @param string "" to create
|
||||
* @param string new name
|
||||
* @param array of array($orig, $process_field, $after)
|
||||
* @param array of strings
|
||||
* @param string
|
||||
* @param string
|
||||
* @param string
|
||||
* @param int
|
||||
* @param string
|
||||
* @return bool
|
||||
*/
|
||||
function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
|
||||
global $connection;
|
||||
$alter = array();
|
||||
foreach ($fields as $field) {
|
||||
$alter[] = ($field[1]
|
||||
? ($table != "" ? ($field[0] != "" ? "CHANGE " . idf_escape($field[0]) : "ADD") : " ") . " " . implode("", $field[1]) . ($table != "" ? " $field[2]" : "")
|
||||
: "DROP " . idf_escape($field[0])
|
||||
);
|
||||
}
|
||||
$alter = array_merge($alter, $foreign);
|
||||
$status = "COMMENT=" . $connection->quote($comment)
|
||||
. ($engine ? " ENGINE=" . $connection->quote($engine) : "")
|
||||
. ($collation ? " COLLATE " . $connection->quote($collation) : "")
|
||||
. ($auto_increment != "" ? " AUTO_INCREMENT=$auto_increment" : "")
|
||||
. $partitioning
|
||||
;
|
||||
if ($table == "") {
|
||||
return queries("CREATE TABLE " . idf_escape($name) . " (\n" . implode(",\n", $alter) . "\n) $status");
|
||||
}
|
||||
if ($table != $name) {
|
||||
$alter[] = "RENAME TO " . idf_escape($name);
|
||||
}
|
||||
$alter[] = $status;
|
||||
return queries("ALTER TABLE " . idf_escape($table) . "\n" . implode(",\n", $alter));
|
||||
}
|
||||
|
||||
/** Run commands to alter indexes
|
||||
* @param string escaped table name
|
||||
* @param array of array("index type", "(columns definition)") or array("index type", "escaped name", "DROP")
|
||||
* @return bool
|
||||
*/
|
||||
function alter_indexes($table, $alter) {
|
||||
foreach ($alter as $key => $val) {
|
||||
$alter[$key] = ($val[2] ? "\nDROP INDEX " : "\nADD $val[0] " . ($val[0] == "PRIMARY" ? "KEY " : "")) . $val[1];
|
||||
}
|
||||
return queries("ALTER TABLE " . idf_escape($table) . implode(",", $alter));
|
||||
}
|
||||
|
||||
/** Run commands to truncate tables
|
||||
* @param array
|
||||
* @return bool
|
||||
*/
|
||||
function truncate_tables($tables) {
|
||||
foreach ($tables as $table) {
|
||||
if (!queries("TRUNCATE TABLE " . idf_escape($table))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Drop views
|
||||
* @param array
|
||||
* @return bool
|
||||
*/
|
||||
function drop_views($views) {
|
||||
return queries("DROP VIEW " . implode(", ", array_map('idf_escape', $views)));
|
||||
}
|
||||
|
||||
/** Drop tables
|
||||
* @param array
|
||||
* @return bool
|
||||
*/
|
||||
function drop_tables($tables) {
|
||||
return queries("DROP TABLE " . implode(", ", array_map('idf_escape', $tables)));
|
||||
}
|
||||
|
||||
/** Get information about trigger
|
||||
* @param string trigger name
|
||||
* @return array array("Trigger" => , "Timing" => , "Event" => , "Statement" => )
|
||||
*/
|
||||
function trigger($name) {
|
||||
global $connection;
|
||||
$result = $connection->query("SHOW TRIGGERS WHERE `Trigger` = " . $connection->quote($name));
|
||||
return $result->fetch_assoc();
|
||||
}
|
||||
|
||||
/** Get defined triggers
|
||||
* @param string
|
||||
* @return array array($name => array($timing, $event))
|
||||
*/
|
||||
function triggers($table) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SHOW TRIGGERS LIKE " . $connection->quote(addcslashes($table, "%_")));
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["Trigger"]] = array($row["Timing"], $row["Event"]);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Explain select
|
||||
* @param Min_DB
|
||||
* @param string
|
||||
* @return Min_Result
|
||||
*/
|
||||
function explain($connection, $query) {
|
||||
return $connection->query("EXPLAIN $query");
|
||||
}
|
||||
|
||||
/** Get SQL command to create table
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function create_sql($table) {
|
||||
global $connection;
|
||||
return $connection->result("SHOW CREATE TABLE " . idf_escape($table), 1);
|
||||
}
|
||||
|
||||
/** Check whether a feature is supported
|
||||
* @param string
|
||||
* @return bool
|
||||
*/
|
||||
function support($feature) {
|
||||
global $connection;
|
||||
$features = array(
|
||||
"view" => ($connection->server_info >= 5),
|
||||
"routine" => ($connection->server_info >= 5),
|
||||
"trigger" => ($connection->server_info >= 5),
|
||||
"event" => ($connection->server_info >= 5.1),
|
||||
"partitioning" => ($connection->server_info >= 5.1),
|
||||
);
|
||||
return (isset($features[$feature]) ? $features[$feature] : true);
|
||||
}
|
||||
|
||||
$driver = "sql"; ///< @var string JUSH identifier
|
||||
$types = array(); ///< @var array ($type => $maximum_unsigned_length, ...)
|
||||
$structured_types = array(); ///< @var array ($description => array($type, ...), ...)
|
||||
foreach (array(
|
||||
lang('Numbers') => array("tinyint" => 3, "smallint" => 5, "mediumint" => 8, "int" => 10, "bigint" => 20, "decimal" => 66, "float" => 12, "double" => 21),
|
||||
lang('Date and time') => array("date" => 10, "datetime" => 19, "timestamp" => 19, "time" => 10, "year" => 4),
|
||||
lang('Strings') => array("char" => 255, "varchar" => 65535, "tinytext" => 255, "text" => 65535, "mediumtext" => 16777215, "longtext" => 4294967295),
|
||||
lang('Binary') => array("binary" => 255, "varbinary" => 65535, "tinyblob" => 255, "blob" => 65535, "mediumblob" => 16777215, "longblob" => 4294967295),
|
||||
lang('Lists') => array("enum" => 65535, "set" => 64),
|
||||
) as $key => $val) {
|
||||
$types += $val;
|
||||
$structured_types[$key] = array_keys($val);
|
||||
}
|
||||
$unsigned = array("unsigned", "zerofill", "unsigned zerofill"); ///< @var array number variants
|
||||
$operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "REGEXP", "IN", "IS NULL", "NOT LIKE", "NOT REGEXP", "NOT IN", "IS NOT NULL"); ///< @var array operators used in select
|
||||
$functions = array("char_length", "from_unixtime", "hex", "lower", "round", "sec_to_time", "time_to_sec", "upper"); ///< @var array functions used in select
|
||||
$grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum"); ///< @var array grouping functions used in select
|
||||
$edit_functions = array( ///< @var array of array("$type|$type2" => "$function/$function2") functions used in editing, [0] - edit and insert, [1] - edit only
|
||||
array(
|
||||
"char" => "md5/sha1/password/encrypt/uuid", //! JavaScript for disabling maxlength
|
||||
"date|time" => "now",
|
||||
), array(
|
||||
"int|float|double|decimal" => "+/-",
|
||||
"date" => "+ interval/- interval",
|
||||
"time" => "addtime/subtime",
|
||||
"char|text" => "concat",
|
||||
)
|
||||
);
|
||||
}
|
443
adminer/drivers/pgsql.inc.php
Normal file
443
adminer/drivers/pgsql.inc.php
Normal file
|
@ -0,0 +1,443 @@
|
|||
<?php
|
||||
$possible_drivers[] = "PgSQL";
|
||||
$possible_drivers[] = "PDO_PgSQL";
|
||||
if (extension_loaded("pgsql") || extension_loaded("pdo_pgsql")) {
|
||||
$drivers["pgsql"] = "PostgreSQL";
|
||||
}
|
||||
|
||||
if (isset($_GET["pgsql"])) {
|
||||
define("DRIVER", "pgsql");
|
||||
if (extension_loaded("pgsql")) {
|
||||
class Min_DB {
|
||||
var $extension = "PgSQL", $_link, $_result, $_string, $_database = true, $server_info, $affected_rows, $error;
|
||||
|
||||
function _error($errno, $error) {
|
||||
if (ini_bool("html_errors")) {
|
||||
$error = html_entity_decode(strip_tags($error));
|
||||
}
|
||||
$error = ereg_replace('^[^:]*: ', '', $error);
|
||||
$this->error = $error;
|
||||
}
|
||||
|
||||
function connect($server, $username, $password) {
|
||||
set_error_handler(array($this, '_error'));
|
||||
$this->_string = "host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' user='" . addcslashes($username, "'\\") . "' password='" . addcslashes($password, "'\\") . "'";
|
||||
$this->_link = @pg_connect($this->_string . (DB != "" ? " dbname='" . addcslashes(DB, "'\\") . "'" : ""), PGSQL_CONNECT_FORCE_NEW);
|
||||
if (!$this->_link && DB != "") {
|
||||
// try to connect directly with database for performance
|
||||
$this->_database = false;
|
||||
$this->_link = @pg_connect($this->_string, PGSQL_CONNECT_FORCE_NEW);
|
||||
}
|
||||
restore_error_handler();
|
||||
if ($this->_link) {
|
||||
$version = pg_version($this->_link);
|
||||
$this->server_info = $version["server"];
|
||||
pg_set_client_encoding($this->_link, "UTF8");
|
||||
}
|
||||
return (bool) $this->_link;
|
||||
}
|
||||
|
||||
function quote($string) {
|
||||
return "'" . pg_escape_string($this->_link, $string) . "'"; //! bytea
|
||||
}
|
||||
|
||||
function select_db($database) {
|
||||
if ($database == DB) {
|
||||
return $this->_database;
|
||||
}
|
||||
$link = @pg_connect($this->_connection . " dbname='" . addcslashes($database, "'\\") . "'", PGSQL_CONNECT_FORCE_NEW);
|
||||
if ($link) {
|
||||
$this->_link = $link;
|
||||
}
|
||||
return $link;
|
||||
}
|
||||
|
||||
function query($query, $unbuffered = false) {
|
||||
$result = @pg_query($this->_link, $query);
|
||||
if (!$result) {
|
||||
$this->error = pg_last_error($this->_link);
|
||||
return false;
|
||||
} elseif (!pg_num_fields($result)) {
|
||||
$this->affected_rows = pg_affected_rows($result);
|
||||
return true;
|
||||
}
|
||||
return new Min_Result($result);
|
||||
}
|
||||
|
||||
function multi_query($query) {
|
||||
return $this->_result = $this->query($query);
|
||||
}
|
||||
|
||||
function store_result() {
|
||||
return $this->_result;
|
||||
}
|
||||
|
||||
function next_result() {
|
||||
// PgSQL extension doesn't support multiple results
|
||||
return false;
|
||||
}
|
||||
|
||||
function result($query, $field = 0) {
|
||||
$result = $this->query($query);
|
||||
if (!$result) {
|
||||
return false;
|
||||
}
|
||||
return pg_fetch_result($result->_result, 0, $field);
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
var $_result, $_offset = 0, $num_rows;
|
||||
|
||||
function Min_Result($result) {
|
||||
$this->_result = $result;
|
||||
$this->num_rows = pg_num_rows($result);
|
||||
}
|
||||
|
||||
function fetch_assoc() {
|
||||
return pg_fetch_assoc($this->_result);
|
||||
}
|
||||
|
||||
function fetch_row() {
|
||||
return pg_fetch_row($this->_result);
|
||||
}
|
||||
|
||||
function fetch_field() {
|
||||
$column = $this->_offset++;
|
||||
$row = new stdClass;
|
||||
$row->orgtable = pg_field_table($this->_result, $column);
|
||||
$row->name = pg_field_name($this->_result, $column);
|
||||
$row->orgname = $row->name;
|
||||
$row->type = pg_field_type($this->_result, $column);
|
||||
$row->charsetnr = ($row->type == "bytea" ? 63 : 0);
|
||||
return $row;
|
||||
}
|
||||
|
||||
function __destruct() {
|
||||
pg_free_result($this->_result);
|
||||
}
|
||||
}
|
||||
|
||||
} elseif (extension_loaded("pdo_pgsql")) {
|
||||
class Min_DB extends Min_PDO {
|
||||
var $extension = "PDO_PgSQL";
|
||||
|
||||
function connect($server, $username, $password) {
|
||||
$string = "pgsql:host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' options='-c client_encoding=utf8'";
|
||||
$this->dsn($string . (DB != "" ? " dbname='" . addcslashes(DB, "'\\") . "'" : ""), $username, $password);
|
||||
//! connect without DB in case of an error
|
||||
return true;
|
||||
}
|
||||
|
||||
function select_db($database) {
|
||||
return (DB == $database);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function idf_escape($idf) {
|
||||
return '"' . str_replace('"', '""', $idf) . '"';
|
||||
}
|
||||
|
||||
function connect() {
|
||||
global $adminer;
|
||||
$connection = new Min_DB;
|
||||
$credentials = $adminer->credentials();
|
||||
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
|
||||
return $connection;
|
||||
}
|
||||
return $connection->error;
|
||||
}
|
||||
|
||||
function get_databases() {
|
||||
return get_vals("SELECT datname FROM pg_database");
|
||||
}
|
||||
|
||||
function limit($query, $limit, $offset = 0) {
|
||||
return " $query" . (isset($limit) ? "\nLIMIT $limit" . ($offset ? " OFFSET $offset" : "") : "");
|
||||
}
|
||||
|
||||
function limit1($query) {
|
||||
return " $query";
|
||||
}
|
||||
|
||||
function db_collation($db, $collations) {
|
||||
global $connection;
|
||||
return $connection->result("SHOW LC_COLLATE"); //! respect $db
|
||||
}
|
||||
|
||||
function engines() {
|
||||
return array();
|
||||
}
|
||||
|
||||
function logged_user() {
|
||||
global $connection;
|
||||
return $connection->result("SELECT user");
|
||||
}
|
||||
|
||||
function tables_list() {
|
||||
global $connection;
|
||||
return get_key_vals("SELECT table_name, table_type FROM information_schema.tables WHERE table_schema = 'public' ORDER BY table_name");
|
||||
}
|
||||
|
||||
function count_tables($databases) {
|
||||
return array(); // would require reconnect
|
||||
}
|
||||
|
||||
function table_status($name = "") {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SELECT relname AS \"Name\", CASE relkind WHEN 'r' THEN '' ELSE 'view' END AS \"Engine\", pg_relation_size(oid) AS \"Data_length\", pg_catalog.obj_description(oid, 'pg_class') AS \"Comment\" FROM pg_catalog.pg_class WHERE relkind IN ('r','v') AND relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public')" . ($name != "" ? " AND relname = " . $connection->quote($name) : "")); //! Index_length, Auto_increment
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["Name"]] = $row;
|
||||
}
|
||||
return ($name != "" ? $return[$name] : $return);
|
||||
}
|
||||
|
||||
function fk_support($table_status) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function fields($table) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$table_oid = $connection->result("SELECT oid FROM pg_class WHERE relname = " . $connection->quote($table));
|
||||
$result = $connection->query("SELECT *, col_description($table_oid, ordinal_position) AS comment FROM information_schema.columns WHERE table_name = " . $connection->quote($table) . " ORDER BY ordinal_position");
|
||||
if ($result) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$length = $row["character_maximum_length"];
|
||||
$return[$row["column_name"]] = array(
|
||||
"field" => $row["column_name"],
|
||||
"full_type" => $row["data_type"] . ($length ? "($length)" : ""),
|
||||
"type" => $row["data_type"],
|
||||
"length" => $length,
|
||||
"default" => $row["column_default"],
|
||||
"null" => ($row["is_nullable"] == "YES"),
|
||||
"auto_increment" => eregi("^nextval\\(", $row["column_default"]),
|
||||
"on_update" => "", //!
|
||||
"collation" => $row["collation_name"],
|
||||
"privileges" => array("insert" => 1, "select" => 1, "update" => 1), //! is_updatable
|
||||
"primary" => false, //!
|
||||
"comment" => $row["comment"],
|
||||
);
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function indexes($table, $connection2 = null) {
|
||||
global $connection;
|
||||
if (!is_object($connection2)) {
|
||||
$connection2 = $connection;
|
||||
}
|
||||
$return = array();
|
||||
$table_oid = $connection2->result("SELECT oid FROM pg_class WHERE relname = " . $connection2->quote($table));
|
||||
$columns = get_key_vals("SELECT attnum, attname FROM pg_attribute WHERE attrelid = $table_oid AND attnum > 0", $connection2);
|
||||
$result = $connection2->query("SELECT relname, indisunique, indisprimary, indkey FROM pg_index i, pg_class ci WHERE i.indrelid = $table_oid AND ci.oid = i.indexrelid");
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["relname"]]["type"] = ($row["indisprimary"] == "t" ? "PRIMARY" : ($row["indisunique"] == "t" ? "UNIQUE" : "INDEX"));
|
||||
$return[$row["relname"]]["columns"] = array();
|
||||
foreach (explode(" ", $row["indkey"]) as $indkey) {
|
||||
$return[$row["relname"]]["columns"][] = $columns[$indkey];
|
||||
}
|
||||
$return[$row["relname"]]["lengths"] = array();
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function foreign_keys($table) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SELECT tc.constraint_name, kcu.column_name, rc.update_rule AS on_update, rc.delete_rule AS on_delete, ccu.table_name AS table, ccu.column_name AS ref
|
||||
FROM information_schema.table_constraints tc
|
||||
LEFT JOIN information_schema.key_column_usage kcu USING (constraint_catalog, constraint_schema, constraint_name)
|
||||
LEFT JOIN information_schema.referential_constraints rc USING (constraint_catalog, constraint_schema, constraint_name)
|
||||
LEFT JOIN information_schema.constraint_column_usage ccu ON rc.unique_constraint_catalog = ccu.constraint_catalog AND rc.unique_constraint_schema = ccu.constraint_schema AND rc.unique_constraint_name = ccu.constraint_name
|
||||
WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name = " . $connection->quote($table)); //! there can be more unique_constraint_name
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$foreign_key = &$return[$row["constraint_name"]];
|
||||
if (!$foreign_key) {
|
||||
$foreign_key = $row;
|
||||
}
|
||||
$foreign_key["source"][] = $row["column_name"];
|
||||
$foreign_key["target"][] = $row["ref"];
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function view($name) {
|
||||
global $connection;
|
||||
return array("select" => $connection->result("SELECT pg_get_viewdef(" . $connection->quote($name) . ")"));
|
||||
}
|
||||
|
||||
function collations() {
|
||||
//! supported in CREATE DATABASE
|
||||
return array();
|
||||
}
|
||||
|
||||
function information_schema($db) {
|
||||
return ($db == "information_schema");
|
||||
}
|
||||
|
||||
function error() {
|
||||
global $connection;
|
||||
$return = h($connection->error);
|
||||
if (preg_match('~^(.*\\n)?([^\\n]*)\\n( *)\\^(\\n.*)?$~s', $return, $match)) {
|
||||
$return = $match[1] . preg_replace('~((?:[^&]|&[^;]*;){' . strlen($match[3]) . '})(.*)~', '\\1<b>\\2</b>', $match[2]) . $match[4];
|
||||
}
|
||||
return nl_br($return);
|
||||
}
|
||||
|
||||
function exact_value($val) {
|
||||
global $connection;
|
||||
return $connection->quote($val);
|
||||
}
|
||||
|
||||
function rename_database($name, $collation) {
|
||||
//! current database cannot be renamed
|
||||
return queries("ALTER DATABASE " . idf_escape(DB) . " RENAME TO " . idf_escape($name));
|
||||
}
|
||||
|
||||
function auto_increment() {
|
||||
return true;
|
||||
}
|
||||
|
||||
function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
|
||||
global $connection;
|
||||
$alter = array();
|
||||
$queries = array();
|
||||
foreach ($fields as $field) {
|
||||
$column = idf_escape($field[0]);
|
||||
$val = $field[1];
|
||||
if (!$val) {
|
||||
$alter[] = "DROP $column";
|
||||
} else {
|
||||
$val5 = $val[5];
|
||||
unset($val[5]);
|
||||
if ($val[6]) { // auto_increment
|
||||
$val = array($val[0], ($val[1] == "bigint" ? "big" : "") . "serial");
|
||||
}
|
||||
if ($field[0] == "") {
|
||||
$alter[] = ($table != "" ? "ADD " : " ") . implode("", $val);
|
||||
} else {
|
||||
if ($column != $val[0]) {
|
||||
$queries[] = "ALTER TABLE " . idf_escape($table) . " RENAME $column TO $val[0]";
|
||||
}
|
||||
$alter[] = "ALTER $column TYPE $val[1]";
|
||||
if (!$val[6]) {
|
||||
$alter[] = "ALTER $column" . ($val[3] ? " SET$val[3]" : " DROP DEFAULT"); //! quoting
|
||||
$alter[] = "ALTER $column " . ($val[2] == " NULL" ? "DROP NOT" : "SET") . $val[2];
|
||||
}
|
||||
}
|
||||
if ($table != "" || $val5 != "") {
|
||||
$queries[] = "COMMENT ON COLUMN " . idf_escape($table) . ".$val[0] IS " . substr($val5, 9);
|
||||
}
|
||||
}
|
||||
}
|
||||
$alter = array_merge($alter, $foreign);
|
||||
if ($table == "") {
|
||||
array_unshift($queries, "CREATE TABLE " . idf_escape($name) . " (\n" . implode(",\n", $alter) . "\n)");
|
||||
} elseif ($alter) {
|
||||
array_unshift($queries, "ALTER TABLE " . idf_escape($table) . "\n" . implode(",\n", $alter));
|
||||
}
|
||||
if ($table != "" && $table != $name) {
|
||||
$queries[] = "ALTER TABLE " . idf_escape($table) . " RENAME TO " . idf_escape($name);
|
||||
}
|
||||
if ($table != "" || $comment != "") {
|
||||
$queries[] = "COMMENT ON TABLE " . idf_escape($name) . " IS " . $connection->quote($comment);
|
||||
}
|
||||
if ($auto_increment != "") {
|
||||
//! $queries[] = "SELECT setval(pg_get_serial_sequence(" . $connection->quote($name) . ", ), $auto_increment)";
|
||||
}
|
||||
foreach ($queries as $query) {
|
||||
if (!queries($query)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function alter_indexes($table, $alter) {
|
||||
$create = array();
|
||||
$drop = array();
|
||||
foreach ($alter as $val) {
|
||||
if ($val[0] != "INDEX") {
|
||||
$create[] = ($val[2] ? "\nDROP CONSTRAINT " : "\nADD $val[0] " . ($val[0] == "PRIMARY" ? "KEY " : "")) . $val[1];
|
||||
} elseif ($val[2]) {
|
||||
$drop[] = $val[1];
|
||||
} elseif (!queries("CREATE INDEX " . idf_escape(uniqid($table . "_")) . " ON " . idf_escape($table) . " $val[1]")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return ((!$create || queries("ALTER TABLE " . idf_escape($table) . implode(",", $create)))
|
||||
&& (!$drop || queries("DROP INDEX " . implode(", ", $drop)))
|
||||
);
|
||||
}
|
||||
|
||||
function truncate_tables($tables) {
|
||||
return queries("TRUNCATE " . implode(", ", array_map('idf_escape', $tables)));
|
||||
return true;
|
||||
}
|
||||
|
||||
function drop_views($views) {
|
||||
return queries("DROP VIEW " . implode(", ", array_map('idf_escape', $views)));
|
||||
}
|
||||
|
||||
function drop_tables($tables) {
|
||||
return queries("DROP TABLE " . implode(", ", array_map('idf_escape', $tables)));
|
||||
}
|
||||
|
||||
function trigger($name) {
|
||||
global $connection;
|
||||
$result = $connection->query('SELECT trigger_name AS "Trigger", condition_timing AS "Timing", event_manipulation AS "Event", action_statement AS "Statement" FROM information_schema.triggers WHERE event_object_table = ' . $connection->quote($_GET["trigger"]) . ' AND trigger_name = ' . $connection->quote($name));
|
||||
return $result->fetch_assoc();
|
||||
}
|
||||
|
||||
function triggers($table) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SELECT * FROM information_schema.triggers WHERE event_object_table = " . $connection->quote($table));
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["trigger_name"]] = array($row["condition_timing"], $row["event_manipulation"]);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function explain($connection, $query) {
|
||||
return $connection->query("EXPLAIN $query");
|
||||
}
|
||||
|
||||
function support($feature) {
|
||||
return ereg('^(comment|view|routine|trigger)$', $feature);
|
||||
}
|
||||
|
||||
$driver = "pgsql";
|
||||
$types = array();
|
||||
$structured_types = array();
|
||||
foreach (array( //! arrays
|
||||
lang('Numbers') => array("smallint" => 5, "integer" => 10, "bigint" => 19, "boolean" => 1, "numeric" => 0, "real" => 7, "double precision" => 16, "money" => 20),
|
||||
lang('Date and time') => array("date" => 13, "time" => 17, "timestamp" => 20, "interval" => 0),
|
||||
lang('Strings') => array("character" => 0, "character varying" => 0, "text" => 0, "tsquery" => 0, "tsvector" => 0, "uuid" => 0, "xml" => 0),
|
||||
lang('Binary') => array("bit" => 0, "bit varying" => 0, "bytea" => 0),
|
||||
lang('Network') => array("cidr" => 43, "inet" => 43, "macaddr" => 17, "txid_snapshot" => 0),
|
||||
lang('Geometry') => array("box" => 0, "circle" => 0, "line" => 0, "lseg" => 0, "path" => 0, "point" => 0, "polygon" => 0),
|
||||
) as $key => $val) {
|
||||
$types += $val;
|
||||
$structured_types[$key] = array_keys($val);
|
||||
}
|
||||
$unsigned = array();
|
||||
$operators = array("=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL");
|
||||
$functions = array("char_length", "lower", "round", "to_hex", "to_timestamp", "upper");
|
||||
$grouping = array("avg", "count", "count distinct", "max", "min", "sum");
|
||||
$edit_functions = array(
|
||||
array(
|
||||
"char" => "md5",
|
||||
"date|time" => "now",
|
||||
), array(
|
||||
"int|numeric|real|money" => "+/-",
|
||||
"date|time" => "+ interval/- interval", //! escape
|
||||
"char|text" => "||",
|
||||
)
|
||||
);
|
||||
}
|
479
adminer/drivers/sqlite.inc.php
Normal file
479
adminer/drivers/sqlite.inc.php
Normal file
|
@ -0,0 +1,479 @@
|
|||
<?php
|
||||
$possible_drivers[] = "SQLite";
|
||||
$possible_drivers[] = "SQLite3";
|
||||
$possible_drivers[] = "PDO_SQLite";
|
||||
if (extension_loaded("sqlite3") || extension_loaded("pdo_sqlite")) {
|
||||
$drivers["sqlite"] = "SQLite 3";
|
||||
}
|
||||
if (extension_loaded("sqlite") || extension_loaded("pdo_sqlite")) {
|
||||
$drivers["sqlite2"] = "SQLite 2";
|
||||
}
|
||||
|
||||
if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
define("DRIVER", (isset($_GET["sqlite"]) ? "sqlite" : "sqlite2"));
|
||||
if (extension_loaded(isset($_GET["sqlite2"]) ? "sqlite" : "sqlite3")) {
|
||||
if (isset($_GET["sqlite2"])) {
|
||||
|
||||
class Min_SQLite {
|
||||
var $extension = "SQLite", $server_info, $affected_rows, $error, $_connection;
|
||||
|
||||
function __construct() {
|
||||
$this->server_info = sqlite_libversion();
|
||||
}
|
||||
|
||||
function open($filename) {
|
||||
$this->_connection = new SQLiteDatabase($filename);
|
||||
}
|
||||
|
||||
function query($query, $unbuffered = false) {
|
||||
$method = ($unbuffered ? "unbufferedQuery" : "query");
|
||||
$result = @$this->_connection->$method($query, SQLITE_BOTH, $error);
|
||||
if (!$result) {
|
||||
$this->error = $error;
|
||||
return false;
|
||||
} elseif ($result === true) {
|
||||
$this->affected_rows = $this->changes();
|
||||
return true;
|
||||
}
|
||||
return new Min_Result($result);
|
||||
}
|
||||
|
||||
function quote($string) {
|
||||
return "'" . sqlite_escape_string($string) . "'";
|
||||
}
|
||||
|
||||
function result($query, $field = 0) {
|
||||
$result = $this->query($query);
|
||||
if (!$result) {
|
||||
return false;
|
||||
}
|
||||
$row = $result->_result->fetch();
|
||||
return $row[$field];
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
var $_result, $_offset = 0, $num_rows;
|
||||
|
||||
function __construct($result) {
|
||||
$this->_result = $result;
|
||||
if (method_exists($result, 'numRows')) { // not available in unbuffered query
|
||||
$this->num_rows = $result->numRows();
|
||||
}
|
||||
}
|
||||
|
||||
function fetch_assoc() {
|
||||
$row = $this->_result->fetch(SQLITE_ASSOC);
|
||||
if (!$row) {
|
||||
return false;
|
||||
}
|
||||
$return = array();
|
||||
foreach ($row as $key => $val) {
|
||||
$return[($key[0] == '"' ? idf_unescape($key) : $key)] = $val;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function fetch_row() {
|
||||
return $this->_result->fetch(SQLITE_NUM);
|
||||
}
|
||||
|
||||
function fetch_field() {
|
||||
return (object) array(
|
||||
"name" => $this->_result->fieldName($this->_offset++),
|
||||
//! type, orgtable, charsetnr
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
class Min_SQLite extends SQLite3 {
|
||||
var $extension = "SQLite3", $server_info, $affected_rows, $error;
|
||||
|
||||
function __construct() {
|
||||
$version = $this->version();
|
||||
$this->server_info = $version["versionString"];
|
||||
}
|
||||
|
||||
function open($filename) {
|
||||
parent::__construct($filename);
|
||||
}
|
||||
|
||||
function query($query) {
|
||||
$result = @parent::query($query);
|
||||
if (!$result) {
|
||||
$this->error = $this->lastErrorMsg();
|
||||
return false;
|
||||
} elseif ($result->numColumns()) {
|
||||
return new Min_Result($result);
|
||||
}
|
||||
$this->affected_rows = $this->changes();
|
||||
return true;
|
||||
}
|
||||
|
||||
function quote($string) {
|
||||
return "'" . $this->escapeString($string) . "'";
|
||||
}
|
||||
|
||||
function result($query, $field = 0) {
|
||||
$result = $this->query($query);
|
||||
if (!$result) {
|
||||
return false;
|
||||
}
|
||||
$row = $result->_result->fetchArray();
|
||||
return $row[$field];
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
var $_result, $_offset = 0, $num_rows;
|
||||
|
||||
function __construct($result) {
|
||||
$this->_result = $result;
|
||||
$this->num_rows = 1; //!
|
||||
}
|
||||
|
||||
function fetch_assoc() {
|
||||
return $this->_result->fetchArray(SQLITE3_ASSOC);
|
||||
}
|
||||
|
||||
function fetch_row() {
|
||||
return $this->_result->fetchArray(SQLITE3_NUM);
|
||||
}
|
||||
|
||||
function fetch_field() {
|
||||
$column = $this->_offset++;
|
||||
return (object) array(
|
||||
"name" => $this->_result->columnName($column),
|
||||
"type" => $this->_result->columnType($column),
|
||||
//! orgtable, charsetnr
|
||||
);
|
||||
}
|
||||
|
||||
function __desctruct() {
|
||||
return $this->_result->finalize();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Min_DB extends Min_SQLite {
|
||||
|
||||
function select_db($filename) {
|
||||
static $connected = false;
|
||||
if ($connected) {
|
||||
return true;
|
||||
}
|
||||
set_exception_handler('connect_error'); // try/catch is not compatible with PHP 4
|
||||
$this->open($filename);
|
||||
$connected = true;
|
||||
restore_exception_handler();
|
||||
return true;
|
||||
}
|
||||
|
||||
function multi_query($query) {
|
||||
return $this->_result = $this->query($query);
|
||||
}
|
||||
|
||||
function store_result() {
|
||||
return $this->_result;
|
||||
}
|
||||
|
||||
function next_result() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
} elseif (extension_loaded("pdo_sqlite")) {
|
||||
class Min_DB extends Min_PDO {
|
||||
var $extension = "PDO_SQLite";
|
||||
|
||||
function select_db($filename) {
|
||||
static $connected = false;
|
||||
if ($connected) {
|
||||
return true;
|
||||
}
|
||||
$connected = true;
|
||||
$this->dsn(DRIVER . ":$filename", "", "", "connect_error");
|
||||
//! $this->server_info needs to be filled in __construct()
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function idf_escape($idf) {
|
||||
return '"' . str_replace('"', '""', $idf) . '"';
|
||||
}
|
||||
|
||||
function connect() {
|
||||
global $connection;
|
||||
if ($connection) {
|
||||
return $connection; // can connect only once, function to get number of rows doesn't exist anyway
|
||||
}
|
||||
return new Min_DB;
|
||||
}
|
||||
|
||||
function get_databases() {
|
||||
return array();
|
||||
}
|
||||
|
||||
function limit($query, $limit, $offset = 0) {
|
||||
return " $query" . (isset($limit) ? "\nLIMIT $limit" . ($offset ? " OFFSET $offset" : "") : "");
|
||||
}
|
||||
|
||||
function limit1($query) {
|
||||
global $connection;
|
||||
return ($connection->result("SELECT sqlite_compileoption_used('ENABLE_UPDATE_DELETE_LIMIT')") ? limit($query, 1) : " $query");
|
||||
}
|
||||
|
||||
function db_collation($db, $collations) {
|
||||
return null;
|
||||
}
|
||||
|
||||
function engines() {
|
||||
return array();
|
||||
}
|
||||
|
||||
function logged_user() {
|
||||
return ""; //! OS user
|
||||
}
|
||||
|
||||
function tables_list() {
|
||||
return get_key_vals("SELECT name, type FROM sqlite_master WHERE type IN ('table', 'view')", 1);
|
||||
}
|
||||
|
||||
function count_tables($databases) {
|
||||
return array();
|
||||
}
|
||||
|
||||
function table_status($name = "") {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SELECT name AS Name, type AS Engine FROM sqlite_master WHERE type IN ('table', 'view')" . ($name != "" ? " AND name = " . $connection->quote($name) : ""));
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["Name"]] = $row;
|
||||
}
|
||||
$result = $connection->query("SELECT * FROM sqlite_sequence");
|
||||
if ($result) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["name"]]["Auto_increment"] = $row["seq"];
|
||||
}
|
||||
}
|
||||
return ($name != "" ? $return[$name] : $return);
|
||||
}
|
||||
|
||||
function fk_support($table_status) {
|
||||
global $connection;
|
||||
return !$connection->result("SELECT sqlite_compileoption_used('OMIT_FOREIGN_KEY')");
|
||||
}
|
||||
|
||||
function fields($table) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("PRAGMA table_info(" . idf_escape($table) . ")");
|
||||
if (is_object($result)) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$type = strtolower($row["type"]);
|
||||
$return[$row["name"]] = array(
|
||||
"field" => $row["name"],
|
||||
"type" => (eregi("int", $type) ? "integer" : (eregi("char|clob|text", $type) ? "text" : (eregi("blob", $type) ? "blob" : (eregi("real|floa|doub", $type) ? "real" : "numeric")))),
|
||||
"full_type" => $type,
|
||||
"default" => $row["dflt_value"],
|
||||
"null" => !$row["notnull"],
|
||||
"auto_increment" => eregi('^integer$', $type) && $row["pk"], //! possible false positive
|
||||
"collation" => null, //!
|
||||
"privileges" => array("select" => 1, "insert" => 1, "update" => 1),
|
||||
"primary" => $row["pk"],
|
||||
);
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function indexes($table, $connection2 = null) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$primary = array();
|
||||
foreach (fields($table) as $field) {
|
||||
if ($field["primary"]) {
|
||||
$primary[] = $field["field"];
|
||||
}
|
||||
}
|
||||
if ($primary) {
|
||||
$return[""] = array("type" => "PRIMARY", "columns" => $primary, "lengths" => array());
|
||||
}
|
||||
$result = $connection->query("PRAGMA index_list(" . idf_escape($table) . ")");
|
||||
if (is_object($result)) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["name"]]["type"] = ($row["unique"] ? "UNIQUE" : "INDEX");
|
||||
$return[$row["name"]]["lengths"] = array();
|
||||
$result1 = $connection->query("PRAGMA index_info(" . idf_escape($row["name"]) . ")");
|
||||
while ($row1 = $result1->fetch_assoc()) {
|
||||
$return[$row["name"]]["columns"][] = $row1["name"];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function foreign_keys($table) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("PRAGMA foreign_key_list(" . idf_escape($table) . ")");
|
||||
if (is_object($result)) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$foreign_key = &$return[$row["id"]];
|
||||
if (!$foreign_key) {
|
||||
$foreign_key = $row;
|
||||
}
|
||||
$foreign_key["source"][] = $row["from"];
|
||||
$foreign_key["target"][] = $row["to"];
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function view($name) {
|
||||
global $connection;
|
||||
return array("select" => preg_replace('~^(?:[^`"[]+|`[^`]*`|"[^"]*")* AS\\s+~iU', '', $connection->result("SELECT sql FROM sqlite_master WHERE name = " . $connection->quote($name)))); //! identifiers may be inside []
|
||||
}
|
||||
|
||||
function collations() {
|
||||
return get_vals("PRAGMA collation_list", 1);
|
||||
}
|
||||
|
||||
function information_schema($db) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function error() {
|
||||
global $connection;
|
||||
return h($connection->error);
|
||||
}
|
||||
|
||||
function exact_value($val) {
|
||||
global $connection;
|
||||
return $connection->quote($val);
|
||||
}
|
||||
|
||||
function rename_database($name, $collation) {
|
||||
global $connection;
|
||||
$connection->close(); //! not available with all extensions
|
||||
return rename(DB, $name);
|
||||
}
|
||||
|
||||
function auto_increment() {
|
||||
return " PRIMARY KEY" . (DRIVER == "sqlite" ? " AUTOINCREMENT" : "");
|
||||
}
|
||||
|
||||
function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) {
|
||||
global $connection;
|
||||
$alter = array();
|
||||
foreach ($fields as $field) {
|
||||
$alter[] = ($table != "" && $field[0] == "" ? "ADD " : " ") . implode("", $field[1]);
|
||||
}
|
||||
$alter = array_merge($alter, $foreign);
|
||||
if ($table != "") {
|
||||
foreach ($alter as $val) {
|
||||
if (!queries("ALTER TABLE " . idf_escape($table) . " $val")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ($table != $name && !queries("ALTER TABLE " . idf_escape($table) . " RENAME TO " . idf_escape($name))) {
|
||||
return false;
|
||||
}
|
||||
} elseif (!queries("CREATE TABLE " . idf_escape($name) . " (\n" . implode(",\n", $alter) . "\n)")) {
|
||||
return false;
|
||||
}
|
||||
if ($auto_increment) {
|
||||
return queries("UPDATE sqlite_sequence SET seq = $auto_increment WHERE name = " . $connection->quote($name) . "");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function alter_indexes($table, $alter) {
|
||||
foreach ($alter as $val) {
|
||||
if (!queries(($val[2] ? "DROP INDEX" : "CREATE" . ($val[0] != "INDEX" ? " UNIQUE" : "") . " INDEX " . idf_escape(uniqid($table . "_")) . " ON " . idf_escape($table)) . " $val[1]")) { //! primary key must be created in CREATE TABLE
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function truncate_tables($tables) {
|
||||
foreach ($tables as $table) {
|
||||
if (!queries("DELETE FROM " . idf_escape($table))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function drop_views($views) {
|
||||
foreach ($views as $view) {
|
||||
if (!queries("DROP VIEW " . idf_escape($view))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function drop_tables($tables) {
|
||||
foreach ($tables as $table) {
|
||||
if (!queries("DROP TABLE " . idf_escape($table))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function trigger($name) {
|
||||
global $connection;
|
||||
preg_match('~^CREATE\\s+TRIGGER\\s*(?:[^`"\\s]+|`[^`]*`|"[^"]*")+\\s*([a-z]+)\\s+([a-z]+)\\s+ON\\s*(?:[^`"\\s]+|`[^`]*`|"[^"]*")+\\s*(?:FOR\\s*EACH\\s*ROW\\s)?(.*)~is', $connection->result("SELECT sql FROM sqlite_master WHERE name = " . $connection->quote($name)), $match);
|
||||
return array("Timing" => strtoupper($match[1]), "Event" => strtoupper($match[2]), "Trigger" => $name, "Statement" => $match[3]);
|
||||
}
|
||||
|
||||
function triggers($table) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SELECT * FROM sqlite_master WHERE type = 'trigger' AND tbl_name = " . $connection->quote($table));
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
preg_match('~^CREATE\\s+TRIGGER\\s*(?:[^`"\\s]+|`[^`]*`|"[^"]*")+\\s*([a-z]+)\\s*([a-z]+)~i', $row["sql"], $match);
|
||||
$return[$row["name"]] = array($match[1], $match[2]);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function explain($connection, $query) {
|
||||
return $connection->query("EXPLAIN $query");
|
||||
}
|
||||
|
||||
function create_sql($table) {
|
||||
global $connection;
|
||||
return $connection->result("SELECT sql FROM sqlite_master WHERE name = " . $connection->quote($table));
|
||||
}
|
||||
|
||||
function support($feature) {
|
||||
return ereg('^(view|trigger)$', $feature);
|
||||
}
|
||||
|
||||
$driver = "sqlite";
|
||||
$types = array("integer" => 0, "real" => 0, "numeric" => 0, "text" => 0, "blob" => 0);
|
||||
$structured_types = array_keys($types);
|
||||
$unsigned = array();
|
||||
$operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "LIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL"); // REGEXP can be user defined function
|
||||
$functions = array("hex", "length", "lower", "round", "unixepoch", "upper");
|
||||
$grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum");
|
||||
$edit_functions = array(
|
||||
array(
|
||||
// "text" => "date('now')/time('now')/datetime('now')",
|
||||
), array(
|
||||
"integer|real|numeric" => "+/-",
|
||||
// "text" => "date/time/datetime",
|
||||
"text" => "||",
|
||||
)
|
||||
);
|
||||
}
|
|
@ -2,25 +2,37 @@
|
|||
$TABLE = $_GET["dump"];
|
||||
|
||||
if ($_POST) {
|
||||
$cookie = "";
|
||||
foreach (array("output", "format", "db_style", "table_style", "data_style") as $key) {
|
||||
$cookie .= "&$key=" . urlencode($_POST[$key]);
|
||||
}
|
||||
cookie("adminer_export", substr($cookie, 1));
|
||||
$ext = dump_headers(($TABLE != "" ? $TABLE : DB), (DB == "" || count((array) $_POST["tables"] + (array) $_POST["data"]) > 1));
|
||||
if ($_POST["format"] == "sql") {
|
||||
echo "-- Adminer $VERSION dump
|
||||
SET NAMES utf8;
|
||||
echo "-- Adminer $VERSION " . $drivers[DRIVER] . " dump
|
||||
|
||||
" . ($driver != "sql" ? "" : "SET NAMES utf8;
|
||||
SET foreign_key_checks = 0;
|
||||
SET time_zone = " . $connection->quote($connection->result($connection->query("SELECT @@time_zone"))) . ";
|
||||
SET time_zone = " . $connection->quote($connection->result("SELECT @@time_zone")) . ";
|
||||
SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
|
||||
|
||||
";
|
||||
");
|
||||
}
|
||||
|
||||
$style = $_POST["db_style"];
|
||||
foreach ((DB != "" ? array(DB) : (array) $_POST["databases"]) as $db) {
|
||||
$databases = array(DB);
|
||||
if (DB == "") {
|
||||
$databases = $_POST["databases"];
|
||||
if (is_string($databases)) {
|
||||
$databases = explode("\n", rtrim(str_replace("\r", "", $databases), "\n"));
|
||||
}
|
||||
}
|
||||
foreach ((array) $databases as $db) {
|
||||
if ($connection->select_db($db)) {
|
||||
if ($_POST["format"] == "sql" && ereg('CREATE', $style) && ($result = $connection->query("SHOW CREATE DATABASE " . idf_escape($db)))) {
|
||||
if ($_POST["format"] == "sql" && ereg('CREATE', $style) && ($create = $connection->result("SHOW CREATE DATABASE " . idf_escape($db), 1))) {
|
||||
if ($style == "DROP+CREATE") {
|
||||
echo "DROP DATABASE IF EXISTS " . idf_escape($db) . ";\n";
|
||||
}
|
||||
$create = $connection->result($result, 1);
|
||||
echo ($style == "CREATE+ALTER" ? preg_replace('~^CREATE DATABASE ~', '\\0IF NOT EXISTS ', $create) : $create) . ";\n";
|
||||
}
|
||||
if ($_POST["format"] == "sql") {
|
||||
|
@ -36,7 +48,7 @@ SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
|
|||
$result = $connection->query("SHOW $routine STATUS WHERE Db = " . $connection->quote($db));
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$out .= ($style != 'DROP+CREATE' ? "DROP $routine IF EXISTS " . idf_escape($row["Name"]) . ";;\n" : "")
|
||||
. $connection->result($connection->query("SHOW CREATE $routine " . idf_escape($row["Name"])), 2) . ";;\n\n";
|
||||
. $connection->result("SHOW CREATE $routine " . idf_escape($row["Name"]), 2) . ";;\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +57,7 @@ SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
|
|||
if ($result) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$out .= ($style != 'DROP+CREATE' ? "DROP EVENT IF EXISTS " . idf_escape($row["Name"]) . ";;\n" : "")
|
||||
. $connection->result($connection->query("SHOW CREATE EVENT " . idf_escape($row["Name"])), 3) . ";;\n\n";
|
||||
. $connection->result("SHOW CREATE EVENT " . idf_escape($row["Name"]), 3) . ";;\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +68,7 @@ SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
|
|||
|
||||
if ($_POST["table_style"] || $_POST["data_style"]) {
|
||||
$views = array();
|
||||
//! defer number of rows to JavaScript
|
||||
foreach (table_status() as $row) {
|
||||
$table = (DB == "" || in_array($row["Name"], (array) $_POST["tables"]));
|
||||
$data = (DB == "" || in_array($row["Name"], (array) $_POST["data"]));
|
||||
|
@ -143,22 +156,26 @@ page_header(lang('Export'), "", ($_GET["export"] != "" ? array("table" => $_GET[
|
|||
$db_style = array('', 'USE', 'DROP+CREATE', 'CREATE');
|
||||
$table_style = array('', 'DROP+CREATE', 'CREATE');
|
||||
$data_style = array('', 'TRUNCATE+INSERT', 'INSERT', 'INSERT+UPDATE');
|
||||
if ($connection->server_info >= 5) {
|
||||
if (support("routine")) {
|
||||
$db_style[] = 'CREATE+ALTER';
|
||||
$table_style[] = 'CREATE+ALTER';
|
||||
}
|
||||
echo "<tr><th>" . lang('Output') . "<td><input type='hidden' name='token' value='$token'>" . $adminer->dumpOutput(0) . "\n"; // token is not needed but checked in bootstrap for all POST data //! read from cookie
|
||||
echo "<tr><th>" . lang('Format') . "<td>" . $adminer->dumpFormat(0) . "\n";
|
||||
echo "<tr><th>" . lang('Database') . "<td>" . html_select('db_style', $db_style, (DB != "" ? '' : 'CREATE'));
|
||||
if ($connection->server_info >= 5) {
|
||||
$checked = $_GET["dump"] == "";
|
||||
echo checkbox("routines", 1, $checked, lang('Routines'));
|
||||
if ($connection->server_info >= 5.1) {
|
||||
echo checkbox("events", 1, $checked, lang('Events'));
|
||||
}
|
||||
parse_str($_COOKIE["adminer_export"], $row);
|
||||
if (!$row) {
|
||||
$row = array("output" => "text", "format" => "sql", "db_style" => (DB != "" ? "" : "CREATE"), "table_style" => "DROP+CREATE", "data_style" => "INSERT");
|
||||
}
|
||||
echo "<tr><th>" . lang('Tables') . "<td>" . html_select('table_style', $table_style, 'DROP+CREATE');
|
||||
echo "<tr><th>" . lang('Data') . "<td>" . html_select('data_style', $data_style, 'INSERT');
|
||||
echo "<tr><th>" . lang('Output') . "<td>" . $adminer->dumpOutput(0, $row["output"]) . "\n";
|
||||
echo "<tr><th>" . lang('Format') . "<td>" . $adminer->dumpFormat(0, $row["format"]) . "\n";
|
||||
echo "<tr><th>" . lang('Database') . "<td>" . html_select('db_style', $db_style, $row["db_style"]);
|
||||
$checked = ($_GET["dump"] == "");
|
||||
if (support("routine")) {
|
||||
echo checkbox("routines", 1, $checked, lang('Routines'));
|
||||
}
|
||||
if (support("event")) {
|
||||
echo checkbox("events", 1, $checked, lang('Events'));
|
||||
}
|
||||
echo "<tr><th>" . lang('Tables') . "<td>" . html_select('table_style', $table_style, $row["table_style"]);
|
||||
echo "<tr><th>" . lang('Data') . "<td>" . html_select('data_style', $data_style, $row["data_style"]);
|
||||
?>
|
||||
</table>
|
||||
<p><input type="submit" value="<?php echo lang('Export'); ?>">
|
||||
|
@ -178,22 +195,27 @@ if (DB != "") {
|
|||
$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');");
|
||||
if (!$row["Engine"]) {
|
||||
if (eregi("view", $row["Engine"])) {
|
||||
$views .= "$print\n";
|
||||
} else {
|
||||
echo "$print<td align='right'><label>" . ($row["Engine"] == "InnoDB" && $row["Rows"] ? lang('~ %s', $row["Rows"]) : $row["Rows"]) . checkbox("data[]", $name, $checked, "", "formUncheck('check-data');") . "</label>\n";
|
||||
echo "$print<td align='right'><label>" . ($row["Engine"] == "InnoDB" && $row["Rows"] ? "~ " : "") . $row["Rows"] . checkbox("data[]", $name, $checked, "", "formUncheck('check-data');") . "</label>\n";
|
||||
}
|
||||
$prefixes[$prefix]++;
|
||||
}
|
||||
echo $views;
|
||||
} else {
|
||||
echo "<thead><tr><th style='text-align: left;'><label><input type='checkbox' id='check-databases'" . ($TABLE == "" ? " checked" : "") . " onclick='formCheck(this, /^databases\\[/);'>" . lang('Database') . "</label></thead>\n";
|
||||
foreach (get_databases() as $db) {
|
||||
if (!information_schema($db)) {
|
||||
$prefix = ereg_replace("_.*", "", $db);
|
||||
echo "<tr><td>" . checkbox("databases[]", $db, $TABLE == "" || $TABLE == "$prefix%", $db, "formUncheck('check-databases');") . "</label>\n";
|
||||
$prefixes[$prefix]++;
|
||||
$databases = get_databases();
|
||||
if ($databases) {
|
||||
foreach ($databases as $db) {
|
||||
if (!information_schema($db)) {
|
||||
$prefix = ereg_replace("_.*", "", $db);
|
||||
echo "<tr><td>" . checkbox("databases[]", $db, $TABLE == "" || $TABLE == "$prefix%", $db, "formUncheck('check-databases');") . "</label>\n";
|
||||
$prefixes[$prefix]++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo "<tr><td><textarea name='databases' rows='10' cols='20'></textarea>";
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
|
|
@ -14,30 +14,22 @@ if ($_POST && !$error && !isset($_GET["select"])) {
|
|||
$location = ($update ? null : $_SERVER["REQUEST_URI"]);
|
||||
} elseif (!ereg('^.+&select=.+$', $location)) {
|
||||
$location = ME . "select=" . urlencode($TABLE);
|
||||
$i = 0; // append &set converted to &where
|
||||
foreach ((array) $_GET["set"] as $key => $val) {
|
||||
if ($val == $_POST["fields"][$key]) {
|
||||
$location .= where_link($i++, bracket_escape($key, "back"), $val);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($_POST["delete"])) {
|
||||
query_redirect("DELETE FROM " . idf_escape($_GET["edit"]) . " WHERE $where LIMIT 1", $location, lang('Item has been deleted.'));
|
||||
query_redirect("DELETE" . limit1("FROM " . idf_escape($_GET["edit"]) . "\nWHERE $where"), $location, lang('Item has been deleted.'));
|
||||
} else {
|
||||
$set = array();
|
||||
foreach ($fields as $name => $field) {
|
||||
$val = process_input($field);
|
||||
if (!$update) {
|
||||
$set[idf_escape($name)] = ($val !== false ? $val : "''");
|
||||
} elseif ($val !== false) {
|
||||
$set[] = "\n" . idf_escape($name) . " = $val";
|
||||
if ($val !== false && $val !== null) {
|
||||
$set[idf_escape($name)] = ($update ? "\n" . idf_escape($name) . " = $val" : $val);
|
||||
}
|
||||
}
|
||||
if (!$set) {
|
||||
redirect($location);
|
||||
}
|
||||
if ($update) {
|
||||
query_redirect("UPDATE " . idf_escape($TABLE) . " SET" . implode(",", $set) . "\nWHERE $where\nLIMIT 1", $location, lang('Item has been updated.'));
|
||||
if (!$set) {
|
||||
redirect($location);
|
||||
}
|
||||
query_redirect("UPDATE" . limit1(idf_escape($TABLE) . " SET" . implode(",", $set) . "\nWHERE $where"), $location, lang('Item has been updated.'));
|
||||
} else {
|
||||
query_redirect("INSERT INTO " . idf_escape($TABLE) . " (" . implode(", ", array_keys($set)) . ")\nVALUES (" . implode(", ", $set) . ")", $location, lang('Item has been inserted.'));
|
||||
}
|
||||
|
@ -64,8 +56,11 @@ if ($_POST["save"]) {
|
|||
}
|
||||
$row = array();
|
||||
if ($select) {
|
||||
$result = $connection->query("SELECT " . implode(", ", $select) . " FROM " . idf_escape($TABLE) . " WHERE $where " . (isset($_GET["select"]) ? "HAVING COUNT(*) = 1" : "LIMIT 1"));
|
||||
$result = $connection->query("SELECT" . limit(implode(", ", $select) . " FROM " . idf_escape($TABLE) . " WHERE $where", (isset($_GET["select"]) ? 2 : 1)));
|
||||
$row = $result->fetch_assoc();
|
||||
if (isset($_GET["select"]) && $result->fetch_assoc()) {
|
||||
$row = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
@ -80,7 +75,7 @@ if ($fields) {
|
|||
$default = $_GET["set"][bracket_escape($name)];
|
||||
$value = (isset($row)
|
||||
? ($row[$name] != "" && ereg("enum|set", $field["type"]) ? intval($row[$name]) : $row[$name])
|
||||
: ($_POST["clone"] && $field["auto_increment"] ? "" : (isset($_GET["select"]) ? false : (isset($default) ? $default : $field["default"])))
|
||||
: (!$update && $field["auto_increment"] ? "" : (isset($_GET["select"]) ? false : (isset($default) ? $default : $field["default"])))
|
||||
);
|
||||
if (!$_POST["save"] && is_string($value)) {
|
||||
$value = $adminer->editVal($value, $field);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
$TABLE = $_GET["foreign"];
|
||||
if ($_POST && !$error && !$_POST["add"] && !$_POST["change"] && !$_POST["change-js"]) {
|
||||
if ($_POST["drop"]) {
|
||||
query_redirect("ALTER TABLE " . idf_escape($TABLE) . "\nDROP FOREIGN KEY " . idf_escape($_GET["name"]), ME . "table=" . urlencode($TABLE), lang('Foreign key has been dropped.'));
|
||||
query_redirect("ALTER TABLE " . idf_escape($TABLE) . "\nDROP " . ($driver == "sql" ? "FOREIGN KEY " : "CONSTRAINT ") . idf_escape($_GET["name"]), ME . "table=" . urlencode($TABLE), lang('Foreign key has been dropped.'));
|
||||
} else {
|
||||
$source = array_filter($_POST["source"], 'strlen');
|
||||
ksort($source); // enforce input order
|
||||
|
@ -39,13 +39,19 @@ if ($_POST) {
|
|||
|
||||
$source = array_keys(fields($TABLE)); //! no text and blob
|
||||
$target = ($TABLE === $row["table"] ? $source : array_keys(fields($row["table"])));
|
||||
$referencable = array();
|
||||
foreach (table_status() as $name => $table_status) {
|
||||
if (fk_support($table_status)) {
|
||||
$referencable[] = $name;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<form action="" method="post">
|
||||
<p>
|
||||
<?php if ($row["db"] == "") { ?>
|
||||
<?php echo lang('Target table'); ?>:
|
||||
<?php echo html_select("table", array_keys(table_status_referencable()), $row["table"], "this.form['change-js'].value = '1'; this.form.submit();"); ?>
|
||||
<?php echo html_select("table", $referencable, $row["table"], "this.form['change-js'].value = '1'; this.form.submit();"); ?>
|
||||
<input type="hidden" name="change-js" value="">
|
||||
<noscript><p><input type="submit" name="change" value="<?php echo lang('Change'); ?>"></noscript>
|
||||
<table cellspacing="0">
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
<?php
|
||||
class Adminer {
|
||||
/** @var array functions used in select */
|
||||
var $functions = array("char_length", "from_unixtime", "hex", "lower", "round", "sec_to_time", "time_to_sec", "unix_timestamp", "upper");
|
||||
|
||||
/** @var array grouping functions used in select */
|
||||
var $grouping = array("avg", "count", "count distinct", "group_concat", "max", "min", "sum");
|
||||
|
||||
/** @var array operators used in select */
|
||||
var $operators = array("=", "<", ">", "<=", ">=", "!=", "LIKE", "REGEXP", "IN", "IS NULL", "NOT LIKE", "NOT REGEXP", "NOT IN", "IS NOT NULL");
|
||||
/** @var array operators used in select, null for all operators */
|
||||
var $operators;
|
||||
|
||||
/** Name in title and navigation
|
||||
* @return string
|
||||
|
@ -20,7 +14,7 @@ class Adminer {
|
|||
* @return array ($server, $username, $password)
|
||||
*/
|
||||
function credentials() {
|
||||
return array($_GET["server"], $_SESSION["usernames"][$_GET["server"]], $_SESSION["passwords"][$_GET["server"]]);
|
||||
return array(SERVER, $_GET["username"], get_session("passwords"));
|
||||
}
|
||||
|
||||
/** Get key used for permanent login
|
||||
|
@ -39,14 +33,15 @@ class Adminer {
|
|||
}
|
||||
|
||||
/** Print login form
|
||||
* @param string
|
||||
* @return null
|
||||
*/
|
||||
function loginForm($username) {
|
||||
function loginForm() {
|
||||
global $drivers, $possible_drivers;
|
||||
?>
|
||||
<table cellspacing="0">
|
||||
<tr><th><?php echo lang('Server'); ?><td><input name="server" value="<?php echo h($_GET["server"]); ?>">
|
||||
<tr><th><?php echo lang('Username'); ?><td><input name="username" value="<?php echo h($username); ?>">
|
||||
<tr><th><?php echo lang('System'); ?><td><?php echo (count($possible_drivers) > 3 ? html_select("driver", $drivers, DRIVER) : "<input type='hidden' name='driver' value='" . key($drivers) . "'>" . reset($drivers)); ?></tr>
|
||||
<tr><th><?php echo lang('Server'); ?><td><input name="server" value="<?php echo h(SERVER); ?>">
|
||||
<tr><th><?php echo lang('Username'); ?><td><input name="username" value="<?php echo h($_GET["username"]); ?>">
|
||||
<tr><th><?php echo lang('Password'); ?><td><input type="password" name="password">
|
||||
</table>
|
||||
<?php
|
||||
|
@ -90,10 +85,10 @@ class Adminer {
|
|||
function selectLinks($tableStatus, $set = "") {
|
||||
echo '<p class="tabs">';
|
||||
$links = array("select" => lang('Select data'), "table" => lang('Show structure'));
|
||||
if (isset($tableStatus["Rows"])) {
|
||||
$links["create"] = lang('Alter table');
|
||||
} else {
|
||||
if (eregi("view", $tableStatus["Engine"])) {
|
||||
$links["view"] = lang('Alter view');
|
||||
} else {
|
||||
$links["create"] = lang('Alter table');
|
||||
}
|
||||
if (isset($set)) {
|
||||
$links["edit"] = lang('New item');
|
||||
|
@ -126,7 +121,8 @@ class Adminer {
|
|||
* @return string
|
||||
*/
|
||||
function selectQuery($query) {
|
||||
return "<p><code class='jush-sql'>" . h(str_replace("\n", " ", $query)) . "</code> <a href='" . h(ME) . "sql=" . urlencode($query) . "'>" . lang('Edit') . "</a>\n";
|
||||
global $driver;
|
||||
return "<p><code class='jush-$driver'>" . h(str_replace("\n", " ", $query)) . "</code> <a href='" . h(ME) . "sql=" . urlencode($query) . "'>" . lang('Edit') . "</a>\n";
|
||||
}
|
||||
|
||||
/** Description of a row in a table
|
||||
|
@ -154,7 +150,7 @@ class Adminer {
|
|||
*/
|
||||
function selectVal($val, $link, $field) {
|
||||
$return = ($val != "<i>NULL</i>" && $field["type"] == "char" ? "<code>$val</code>" : $val);
|
||||
if (ereg('blob|binary', $field["type"]) && !is_utf8($val)) {
|
||||
if (ereg('binary|blob|bytea', $field["type"]) && !is_utf8($val)) {
|
||||
$return = lang('%d byte(s)', strlen($val));
|
||||
}
|
||||
return ($link ? "<a href='$link'>$return</a>" : $return);
|
||||
|
@ -175,17 +171,18 @@ class Adminer {
|
|||
* @return null
|
||||
*/
|
||||
function selectColumnsPrint($select, $columns) {
|
||||
global $functions, $grouping;
|
||||
print_fieldset("select", lang('Select'), $select);
|
||||
$i = 0;
|
||||
$fun_group = array(lang('Functions') => $this->functions, lang('Aggregation') => $this->grouping);
|
||||
$fun_group = array(lang('Functions') => $functions, lang('Aggregation') => $grouping);
|
||||
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]'><option>" . optionlist($columns, $val["col"], true) . "</select>)</div>\n";
|
||||
$i++;
|
||||
}
|
||||
echo "<div>" . html_select("columns[$i][fun]", array(-1 => "") + $fun_group, "", "this.nextSibling.onchange();");
|
||||
echo "<select name='columns[$i][col]' onchange='selectAddRow(this);'><option>" . optionlist($columns, null, true) . "</select></div>\n";
|
||||
echo "<div>" . html_select("columns[$i][fun]", array(-1 => "") + $fun_group, "", "this.nextSibling.nextSibling.onchange();");
|
||||
echo "(<select name='columns[$i][col]' onchange='selectAddRow(this);'><option>" . optionlist($columns, null, true) . "</select>)</div>\n";
|
||||
echo "</div></fieldset>\n";
|
||||
}
|
||||
|
||||
|
@ -208,13 +205,13 @@ class Adminer {
|
|||
$i = 0;
|
||||
foreach ((array) $_GET["where"] as $val) {
|
||||
if ("$val[col]$val[val]" != "" && in_array($val["op"], $this->operators)) {
|
||||
echo "<div><select name='where[$i][col]'><option value=''>" . lang('(anywhere)') . optionlist($columns, $val["col"], true) . "</select>";
|
||||
echo "<div><select name='where[$i][col]'><option value=''>(" . lang('anywhere') . ")" . optionlist($columns, $val["col"], true) . "</select>";
|
||||
echo html_select("where[$i][op]", $this->operators, $val["op"]);
|
||||
echo "<input name='where[$i][val]' value='" . h($val["val"]) . "'></div>\n";
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
echo "<div><select name='where[$i][col]' onchange='selectAddRow(this);'><option value=''>" . lang('(anywhere)') . optionlist($columns, null, true) . "</select>";
|
||||
echo "<div><select name='where[$i][col]' onchange='selectAddRow(this);'><option value=''>(" . lang('anywhere') . ")" . optionlist($columns, null, true) . "</select>";
|
||||
echo html_select("where[$i][op]", $this->operators);
|
||||
echo "<input name='where[$i][val]'></div>\n";
|
||||
echo "</div></fieldset>\n";
|
||||
|
@ -286,12 +283,13 @@ class Adminer {
|
|||
* @return array (array(select_expressions), array(group_expressions))
|
||||
*/
|
||||
function selectColumnsProcess($columns, $indexes) {
|
||||
global $functions, $grouping;
|
||||
$select = array(); // select expressions, empty for *
|
||||
$group = array(); // expressions without aggregation - will be used for GROUP BY if an aggregation function is used
|
||||
foreach ((array) $_GET["columns"] as $key => $val) {
|
||||
if ($val["fun"] == "count" || (isset($columns[$val["col"]]) && (!$val["fun"] || in_array($val["fun"], $this->functions) || in_array($val["fun"], $this->grouping)))) {
|
||||
if ($val["fun"] == "count" || (isset($columns[$val["col"]]) && (!$val["fun"] || in_array($val["fun"], $functions) || in_array($val["fun"], $grouping)))) {
|
||||
$select[$key] = apply_sql_function($val["fun"], (isset($columns[$val["col"]]) ? idf_escape($val["col"]) : "*"));
|
||||
if (!in_array($val["fun"], $this->grouping)) {
|
||||
if (!in_array($val["fun"], $grouping)) {
|
||||
$group[] = $select[$key];
|
||||
}
|
||||
}
|
||||
|
@ -314,8 +312,15 @@ class Adminer {
|
|||
}
|
||||
foreach ((array) $_GET["where"] as $val) {
|
||||
if ("$val[col]$val[val]" != "" && in_array($val["op"], $this->operators)) {
|
||||
$in = process_length($val["val"]);
|
||||
$cond = " $val[op]" . (ereg('NULL$', $val["op"]) ? "" : (ereg('IN$', $val["op"]) ? " (" . ($in != "" ? $in : "NULL") . ")" : " " . $this->processInput($fields[$val["col"]], $val["val"])));
|
||||
$cond = " $val[op]";
|
||||
if (ereg('IN$', $val["op"])) {
|
||||
$in = process_length($val["val"]);
|
||||
$cond .= " (" . ($in != "" ? $in : "NULL") . ")";
|
||||
} elseif ($val["op"] == "LIKE %%") {
|
||||
$cond = " LIKE " . $this->processInput($fields[$val["col"]], "%$val[val]%");
|
||||
} elseif (!ereg('NULL$', $val["op"])) {
|
||||
$cond .= " " . $this->processInput($fields[$val["col"]], $val["val"]);
|
||||
}
|
||||
if ($val["col"] != "") {
|
||||
$return[] = idf_escape($val["col"]) . $cond;
|
||||
} else {
|
||||
|
@ -342,8 +347,8 @@ class Adminer {
|
|||
function selectOrderProcess($fields, $indexes) {
|
||||
$return = array();
|
||||
foreach ((array) $_GET["order"] as $key => $val) {
|
||||
if (isset($fields[$val]) || preg_match('~^((COUNT\\(DISTINCT |[A-Z0-9_]+\\()`(?:[^`]|``)+`\\)|COUNT\\(\\*\\))$~', $val)) {
|
||||
$return[] = idf_escape($val) . (isset($_GET["desc"][$key]) ? " DESC" : "");
|
||||
if (isset($fields[$val]) || preg_match('~^((COUNT\\(DISTINCT |[A-Z0-9_]+\\()(`(?:[^`]|``)+`|"(?:[^"]|"")+")\\)|COUNT\\(\\*\\))$~', $val)) { //! MS SQL uses []
|
||||
$return[] = (isset($fields[$val]) ? idf_escape($val) : $val) . (isset($_GET["desc"][$key]) ? " DESC" : "");
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
|
@ -377,10 +382,12 @@ class Adminer {
|
|||
* @return string
|
||||
*/
|
||||
function messageQuery($query) {
|
||||
global $driver;
|
||||
restart_session();
|
||||
$id = "sql-" . count($_SESSION["messages"]);
|
||||
$_SESSION["history"][$_GET["server"]][DB][] = (strlen($query) > 1e6 ? ereg_replace('[\x80-\xFF]+$', '', substr($query, 0, 1e6)) . "\n..." : $query); // [\x80-\xFF] - valid UTF-8, \n - can end by one-line comment
|
||||
return " <a href='#$id' onclick=\"return !toggle('$id');\">" . lang('SQL command') . "</a><div id='$id' class='hidden'><pre class='jush-sql'>" . shorten_utf8($query, 1000) . '</pre><a href="' . h(ME . 'sql=&history=' . (count($_SESSION["history"][$_GET["server"]][DB]) - 1)) . '">' . lang('Edit') . '</a></div>';
|
||||
$history = &get_session("history");
|
||||
$history[DB][] = (strlen($query) > 1e6 ? ereg_replace('[\x80-\xFF]+$', '', substr($query, 0, 1e6)) . "\n..." : $query); // [\x80-\xFF] - valid UTF-8, \n - can end by one-line comment
|
||||
return " <a href='#$id' onclick=\"return !toggle('$id');\">" . lang('SQL command') . "</a><div id='$id' class='hidden'><pre class='jush-$driver'>" . shorten_utf8($query, 1000) . '</pre><p><a href="' . h(ME . 'sql=&history=' . (count($history[DB]) - 1)) . '">' . lang('Edit') . '</a></div>';
|
||||
}
|
||||
|
||||
/** Functions displayed in edit form
|
||||
|
@ -388,31 +395,18 @@ class Adminer {
|
|||
* @return array
|
||||
*/
|
||||
function editFunctions($field) {
|
||||
$return = array("");
|
||||
if (ereg('char|date|time', $field["type"])) {
|
||||
$return = (ereg('char', $field["type"]) ? array("", "md5", "sha1", "password", "encrypt", "uuid") : array("", "now")); //! JavaScript for disabling maxlength
|
||||
}
|
||||
if (!isset($_GET["call"]) && (isset($_GET["select"]) || where($_GET))) {
|
||||
// relative functions
|
||||
if (ereg('int|float|double|decimal', $field["type"])) {
|
||||
$return = array("", "+", "-");
|
||||
}
|
||||
if (ereg('date', $field["type"])) {
|
||||
$return[] = "+ interval";
|
||||
$return[] = "- interval";
|
||||
}
|
||||
if (ereg('time', $field["type"])) {
|
||||
$return[] = "addtime";
|
||||
$return[] = "subtime";
|
||||
}
|
||||
if (ereg('char|text', $field["type"])) {
|
||||
$return[] = "concat";
|
||||
global $edit_functions;
|
||||
$return = ($field["null"] ? "/NULL" : "");
|
||||
foreach ($edit_functions as $key => $functions) {
|
||||
if (!$key || (!isset($_GET["call"]) && (isset($_GET["select"]) || where($_GET)))) { // relative functions
|
||||
foreach ($functions as $pattern => $val) {
|
||||
if (!$pattern || ereg($pattern, $field["type"])) {
|
||||
$return .= "/$val";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($field["null"]) {
|
||||
array_unshift($return, "NULL");
|
||||
}
|
||||
return $return;
|
||||
return explode("/", $return);
|
||||
}
|
||||
|
||||
/** Get options to display edit field
|
||||
|
@ -441,9 +435,9 @@ class Adminer {
|
|||
global $connection;
|
||||
$name = $field["field"];
|
||||
$return = $connection->quote($value);
|
||||
if (ereg('^(now|uuid)$', $function)) {
|
||||
if (ereg('^(now|getdate|uuid)$', $function)) {
|
||||
$return = "$function()";
|
||||
} elseif (ereg('^[+-]$', $function)) {
|
||||
} elseif (ereg('^([+-]|\\|\\|)$', $function)) {
|
||||
$return = idf_escape($name) . " $function $return";
|
||||
} elseif (ereg('^[+-] interval$', $function)) {
|
||||
$return = idf_escape($name) . " $function " . (preg_match("~^([0-9]+|'[0-9.: -]') [A-Z_]+$~i", $value) ? $value : $return);
|
||||
|
@ -457,9 +451,10 @@ class Adminer {
|
|||
|
||||
/** Returns export output options
|
||||
* @param bool generate select (otherwise radio)
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function dumpOutput($select) {
|
||||
function dumpOutput($select, $value = "") {
|
||||
$return = array('text' => lang('open'), 'file' => lang('save'));
|
||||
if (function_exists('gzencode')) {
|
||||
$return['gz'] = 'gzip';
|
||||
|
@ -468,15 +463,16 @@ class Adminer {
|
|||
$return['bz2'] = 'bzip2';
|
||||
}
|
||||
// ZipArchive requires temporary file, ZIP can be created by gzcompress - see PEAR File_Archive
|
||||
return html_select("output", $return, "text", $select);
|
||||
return html_select("output", $return, $value, $select);
|
||||
}
|
||||
|
||||
/** Returns export format options
|
||||
* @param bool generate select (otherwise radio)
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function dumpFormat($select) {
|
||||
return html_select("format", array('sql' => 'SQL', 'csv' => 'CSV'), "sql", $select);
|
||||
function dumpFormat($select, $value = "") {
|
||||
return html_select("format", array('sql' => 'SQL', 'csv' => 'CSV,', 'csv;' => 'CSV;'), $value, $select);
|
||||
}
|
||||
|
||||
/** Prints navigation after Adminer title
|
||||
|
@ -484,7 +480,7 @@ class Adminer {
|
|||
* @return null
|
||||
*/
|
||||
function navigation($missing) {
|
||||
global $VERSION, $connection;
|
||||
global $VERSION, $connection, $token;
|
||||
?>
|
||||
<h1>
|
||||
<a href="http://www.adminer.org/" id="h1"><?php echo $this->name(); ?></a>
|
||||
|
@ -499,19 +495,18 @@ class Adminer {
|
|||
<p class="logout">
|
||||
<a href="<?php echo h(ME); ?>sql="><?php echo bold(lang('SQL command'), isset($_GET["sql"])); ?></a>
|
||||
<a href="<?php echo h(ME); ?>dump=<?php echo urlencode(isset($_GET["table"]) ? $_GET["table"] : $_GET["select"]); ?>"><?php echo bold(lang('Dump'), isset($_GET["dump"])); ?></a>
|
||||
<input type="hidden" name="token" value="<?php echo $_SESSION["tokens"][$_GET["server"]]; ?>">
|
||||
<input type="hidden" name="token" value="<?php echo $token; ?>">
|
||||
<input type="submit" name="logout" value="<?php echo lang('Logout'); ?>">
|
||||
</p>
|
||||
</form>
|
||||
<form action="">
|
||||
<p>
|
||||
<?php echo SID_FORM; ?>
|
||||
<?php if ($_GET["server"] != "") { ?><input type="hidden" name="server" value="<?php echo h($_GET["server"]); ?>"><?php } ?>
|
||||
<?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 if (isset($_GET["sql"])) { ?><input type="hidden" name="sql" value=""><?php } ?>
|
||||
<?php if (isset($_GET["schema"])) { ?><input type="hidden" name="schema" value=""><?php } ?>
|
||||
<?php if (isset($_GET["dump"])) { ?><input type="hidden" name="dump" value=""><?php } ?>
|
||||
<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'" : ""); ?>>
|
||||
</p>
|
||||
</form>
|
||||
<?php
|
||||
|
@ -533,7 +528,7 @@ class Adminer {
|
|||
*/
|
||||
function tablesPrint($tables) {
|
||||
echo "<p id='tables'>\n";
|
||||
foreach ($tables as $table) {
|
||||
foreach ($tables as $table => $type) {
|
||||
echo '<a href="' . h(ME) . 'select=' . urlencode($table) . '">' . bold(lang('select'), $_GET["select"] == $table) . '</a> ';
|
||||
echo '<a href="' . h(ME) . 'table=' . urlencode($table) . '">' . bold($this->tableName(array("Name" => $table)), $_GET["table"] == $table) . "</a><br>\n"; //! Adminer::tableName may work with full table status
|
||||
}
|
||||
|
@ -542,3 +537,6 @@ class Adminer {
|
|||
}
|
||||
|
||||
$adminer = (function_exists('adminer_object') ? adminer_object() : new Adminer);
|
||||
if (!isset($adminer->operators)) {
|
||||
$adminer->operators = $operators;
|
||||
}
|
||||
|
|
|
@ -1,88 +1,100 @@
|
|||
<?php
|
||||
$connection = '';
|
||||
|
||||
if (!$drivers) {
|
||||
page_header(lang('No extension'), lang('None of the supported PHP extensions (%s) are available.', implode(", ", $possible_drivers)), null);
|
||||
page_footer("auth");
|
||||
exit;
|
||||
}
|
||||
|
||||
$token = $_SESSION["token"];
|
||||
if (!$_SESSION["token"]) {
|
||||
$_SESSION["token"] = rand(1, 1e6); // defense against cross-site request forgery
|
||||
}
|
||||
|
||||
if (isset($_POST["server"])) {
|
||||
session_regenerate_id(); // defense against session fixation
|
||||
$_SESSION["usernames"][$_POST["server"]] = $_POST["username"];
|
||||
$_SESSION["passwords"][$_POST["server"]] = $_POST["password"];
|
||||
$_SESSION["passwords"][$_POST["driver"]][$_POST["server"]][$_POST["username"]] = $_POST["password"];
|
||||
if ($_POST["permanent"]) {
|
||||
cookie("adminer_permanent",
|
||||
cookie("adminer_permanent", //! store separately for each driver, server and username to allow several permanent logins
|
||||
base64_encode($_POST["server"])
|
||||
. ":" . base64_encode($_POST["username"])
|
||||
. ":" . base64_encode(encrypt_string($_POST["password"], $adminer->permanentLogin()))
|
||||
. ":" . base64_encode($_POST["driver"])
|
||||
);
|
||||
}
|
||||
if (count($_POST) == ($_POST["permanent"] ? 4 : 3)) { // 3 - server, username, password
|
||||
$location = ((string) $_GET["server"] === $_POST["server"] ? remove_from_uri(session_name()) : preg_replace('~^([^?]*).*~', '\\1', ME) . ($_POST["server"] != "" ? '?server=' . urlencode($_POST["server"]) : ''));
|
||||
if (SID_FORM) {
|
||||
$pos = strpos($location, '?');
|
||||
$location = ($pos ? substr_replace($location, SID . "&", $pos + 1, 0) : "$location?" . SID);
|
||||
}
|
||||
redirect($location);
|
||||
if (count($_POST) == ($_POST["permanent"] ? 5 : 4) // 4 - driver, server, username, password
|
||||
|| DRIVER != $_POST["driver"]
|
||||
|| SERVER != $_POST["server"]
|
||||
|| $_GET["username"] !== $_POST["username"] // "0" == "00"
|
||||
) {
|
||||
preg_match('~([^?]*)\\??(.*)~', remove_from_uri(implode("|", array_keys($drivers)) . "|username|" . session_name()), $match);
|
||||
redirect("$match[1]?"
|
||||
. (SID ? SID . "&" : "")
|
||||
. ($_POST["driver"] != "server" || $_POST["server"] != "" ? urlencode($_POST["driver"]) . "=" . urlencode($_POST["server"]) . "&" : "")
|
||||
. "username=" . urlencode($_POST["username"])
|
||||
. ($match[2] ? "&$match[2]" : "")
|
||||
);
|
||||
}
|
||||
$_GET["server"] = $_POST["server"]; //! used also in ME
|
||||
} elseif ($_POST["logout"]) {
|
||||
$token = $_SESSION["tokens"][$_GET["server"]];
|
||||
if ($token && $_POST["token"] != $token) {
|
||||
page_header(lang('Logout'), lang('Invalid CSRF token. Send the form again.'));
|
||||
page_footer("db");
|
||||
exit;
|
||||
} else {
|
||||
foreach (array("usernames", "passwords", "databases", "tokens", "history") as $val) {
|
||||
unset($_SESSION[$val][$_GET["server"]]);
|
||||
}
|
||||
if (!isset($_SESSION["passwords"])) { // don't require login to logout
|
||||
$_SESSION["passwords"] = array();
|
||||
foreach (array("passwords", "databases", "history") as $key) {
|
||||
set_session($key, null);
|
||||
}
|
||||
cookie("adminer_permanent", "");
|
||||
redirect(substr(preg_replace('~db=[^&]*&~', '', ME), 0, -1), lang('Logout successful.'));
|
||||
redirect(substr(preg_replace('~(username|db)=[^&]*&~', '', ME), 0, -1), lang('Logout successful.'));
|
||||
}
|
||||
} elseif ($_COOKIE["adminer_permanent"] && !isset($_SESSION["usernames"][$_GET["server"]])) {
|
||||
list($server, $username, $cipher) = array_map('base64_decode', explode(":", $_COOKIE["adminer_permanent"]));
|
||||
if (($_GET["server"] == "" && !$_POST) || $server == $_GET["server"]) {
|
||||
} elseif ($_COOKIE["adminer_permanent"]) {
|
||||
list($server, $username, $cipher, $system) = array_map('base64_decode', explode(":", $_COOKIE["adminer_permanent"])); // $driver is a global variable
|
||||
if ($server == SERVER && $username === $_GET["username"] && $system == DRIVER) {
|
||||
session_regenerate_id(); // defense against session fixation
|
||||
$_SESSION["usernames"][$server] = $username;
|
||||
$_SESSION["passwords"][$server] = decrypt_string($cipher, $adminer->permanentLogin());
|
||||
if ($server != $_GET["server"]) {
|
||||
redirect(preg_replace('~^([^?]*).*~', '\\1', ME) . '?server=' . urlencode($server));
|
||||
}
|
||||
set_session("passwords", decrypt_string($cipher, $adminer->permanentLogin()));
|
||||
}
|
||||
//! redirect ?select=tab
|
||||
}
|
||||
|
||||
function auth_error($exception = null) {
|
||||
global $connection, $adminer;
|
||||
global $connection, $adminer, $token;
|
||||
$session_name = session_name();
|
||||
$username = $_SESSION["usernames"][$_GET["server"]];
|
||||
unset($_SESSION["usernames"][$_GET["server"]]);
|
||||
page_header(lang('Login'), (isset($username) ? h($exception ? $exception->getMessage() : (is_string($connection) ? $connection : lang('Invalid credentials.')))
|
||||
: (!$_COOKIE[$session_name] && $_GET[$session_name] && ini_get("session.use_only_cookies") ? lang('Session support must be enabled.')
|
||||
: (($_COOKIE[$session_name] || $_GET[$session_name]) && !isset($_SESSION["passwords"]) ? lang('Session expired, please login again.')
|
||||
: ""))), null);
|
||||
$error = "";
|
||||
if (!$_COOKIE[$session_name] && $_GET[$session_name] && ini_bool("session.use_only_cookies")) {
|
||||
$error = lang('Session support must be enabled.');
|
||||
} elseif (isset($_GET["username"])) {
|
||||
if (($_COOKIE[$session_name] || $_GET[$session_name]) && !$token) {
|
||||
$error = lang('Session expired, please login again.');
|
||||
} else {
|
||||
$password = get_session("passwords");
|
||||
if (isset($password)) {
|
||||
$error = h($exception ? $exception->getMessage() : (is_string($connection) ? $connection : lang('Invalid credentials.')));
|
||||
}
|
||||
}
|
||||
}
|
||||
page_header(lang('Login'), $error, null);
|
||||
echo "<form action='' method='post'>\n";
|
||||
$adminer->loginForm($username);
|
||||
$adminer->loginForm();
|
||||
echo "<div>";
|
||||
hidden_fields($_POST, array("server", "username", "password")); // expired session
|
||||
hidden_fields($_POST, array("driver", "server", "username", "password", "permanent")); // expired session
|
||||
echo "</div>\n";
|
||||
echo "</form>\n";
|
||||
page_footer("auth");
|
||||
}
|
||||
|
||||
$username = &$_SESSION["usernames"][$_GET["server"]];
|
||||
if (!isset($username)) {
|
||||
$username = $_GET["username"]; // default username can be passed in URL
|
||||
if (isset($_GET["username"]) && class_exists("Min_DB")) { // doesn't exists with passing wrong driver
|
||||
$connection = connect();
|
||||
}
|
||||
$connection = (isset($username) ? connect() : '');
|
||||
if (is_string($connection) || !$adminer->login($username, $_SESSION["passwords"][$_GET["server"]])) {
|
||||
if (is_string($connection) || !$adminer->login($_GET["username"], get_session("passwords"))) {
|
||||
auth_error();
|
||||
exit;
|
||||
}
|
||||
unset($username);
|
||||
|
||||
if (!$_SESSION["tokens"][$_GET["server"]]) {
|
||||
$_SESSION["tokens"][$_GET["server"]] = rand(1, 1e6); // defense against cross-site request forgery
|
||||
}
|
||||
$token = $_SESSION["token"]; ///< @var string CSRF protection
|
||||
if (isset($_POST["server"]) && $_POST["token"]) {
|
||||
$_POST["token"] = $_SESSION["tokens"][$_GET["server"]];
|
||||
$_POST["token"] = $token; // reset token after explicit login
|
||||
}
|
||||
$token = $_SESSION["tokens"][$_GET["server"]]; ///< @var string CSRF protection
|
||||
$error = ($_POST ///< @var string
|
||||
? ($_POST["token"] == $token ? "" : lang('Invalid CSRF token. Send the form again.'))
|
||||
: ($_SERVER["REQUEST_METHOD"] != "POST" ? "" : lang('Too big POST data. Reduce the data or increase the %s configuration directive.', '"post_max_size"')) // posted form with no data means that post_max_size exceeded because Adminer always sends token at least
|
||||
|
|
|
@ -39,12 +39,14 @@ if (isset($_GET["file"])) {
|
|||
exit;
|
||||
}
|
||||
|
||||
include "../adminer/include/functions.inc.php";
|
||||
|
||||
if (!isset($_SERVER["REQUEST_URI"])) {
|
||||
$_SERVER["REQUEST_URI"] = $_SERVER["ORIG_PATH_INFO"] . ($_SERVER["QUERY_STRING"] != "" ? "?$_SERVER[QUERY_STRING]" : "");
|
||||
$_SERVER["REQUEST_URI"] = $_SERVER["ORIG_PATH_INFO"] . ($_SERVER["QUERY_STRING"] != "" ? "?$_SERVER[QUERY_STRING]" : ""); // IIS 5 compatibility
|
||||
}
|
||||
|
||||
@ini_set("session.use_trans_sid", false); // protect links in export, @ - may be disabled
|
||||
if (!ini_get("session.auto_start")) {
|
||||
if (!ini_bool("session.auto_start")) {
|
||||
session_name("adminer_sid"); // use specific session name to get own namespace
|
||||
$params = array(0, preg_replace('~\\?.*~', '', $_SERVER["REQUEST_URI"]), "", $_SERVER["HTTPS"] && strcasecmp($_SERVER["HTTPS"], "off"));
|
||||
if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
|
||||
|
@ -75,19 +77,26 @@ if (function_exists("set_magic_quotes_runtime")) {
|
|||
}
|
||||
@set_time_limit(0); // @ - can be disabled
|
||||
|
||||
include "../adminer/include/version.inc.php";
|
||||
include "../adminer/include/functions.inc.php";
|
||||
|
||||
define("DB", $_GET["db"]); // for the sake of speed and size
|
||||
define("SID_FORM", SID && !ini_get("session.use_only_cookies") ? '<input type="hidden" name="' . session_name() . '" value="' . h(session_id()) . '">' : '');
|
||||
define("ME", preg_replace('~^[^?]*/([^?]*).*~', '\\1', $_SERVER["REQUEST_URI"]) . '?' . (SID_FORM ? SID . '&' : '') . ($_GET["server"] != "" ? 'server=' . urlencode($_GET["server"]) . '&' : '') . (DB != "" ? 'db=' . urlencode(DB) . '&' : ''));
|
||||
|
||||
include "../adminer/include/lang.inc.php";
|
||||
include "../adminer/lang/$LANG.inc.php";
|
||||
include "../adminer/include/pdo.inc.php";
|
||||
include "../adminer/drivers/sqlite.inc.php";
|
||||
include "../adminer/drivers/pgsql.inc.php";
|
||||
include "../adminer/drivers/mssql.inc.php";
|
||||
include "../adminer/drivers/mysql.inc.php"; // must be included as last driver
|
||||
|
||||
define("SERVER", $_GET[DRIVER]); // read from pgsql=localhost
|
||||
define("DB", $_GET["db"]); // for the sake of speed and size
|
||||
define("ME", preg_replace('~^[^?]*/([^?]*).*~', '\\1', $_SERVER["REQUEST_URI"]) . '?'
|
||||
. (SID && !$_COOKIE ? SID . '&' : '') // !$_COOKIE - don't pass SID with permanent login
|
||||
. (SERVER !== null ? DRIVER . "=" . urlencode(SERVER) . '&' : '')
|
||||
. (isset($_GET["username"]) ? "username=" . urlencode($_GET["username"]) . '&' : '')
|
||||
. (DB != "" ? 'db=' . urlencode(DB) . '&' : '')
|
||||
);
|
||||
|
||||
include "../adminer/include/version.inc.php";
|
||||
include "./include/adminer.inc.php";
|
||||
include "../adminer/include/design.inc.php";
|
||||
include "../adminer/include/pdo.inc.php";
|
||||
include "../adminer/include/mysql.inc.php";
|
||||
include "../adminer/include/xxtea.inc.php";
|
||||
include "../adminer/include/auth.inc.php";
|
||||
include "./include/connect.inc.php";
|
||||
|
@ -95,7 +104,7 @@ include "./include/editing.inc.php";
|
|||
include "./include/export.inc.php";
|
||||
|
||||
session_cache_limiter(""); // to allow restarting session
|
||||
if (!ini_get("session.use_cookies") || @ini_set("session.use_cookies", false) !== false) { // @ - may be disabled
|
||||
if (!ini_bool("session.use_cookies") || @ini_set("session.use_cookies", false) !== false) { // @ - may be disabled
|
||||
session_write_close(); // improves concurrency if a user opens several pages at once, may be restarted later
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
<?php
|
||||
function connect_error() {
|
||||
global $connection, $VERSION, $token, $error;
|
||||
global $connection, $VERSION, $token, $error, $drivers;
|
||||
$databases = array();
|
||||
if (DB != "") {
|
||||
page_header(lang('Database') . ": " . h(DB), lang('Invalid database.'), false);
|
||||
page_header(lang('Database') . ": " . h(DB), lang('Invalid database.'), true);
|
||||
} else {
|
||||
if ($_POST["db"] && !$error) {
|
||||
unset($_SESSION["databases"][$_GET["server"]]);
|
||||
set_session("databases", null);
|
||||
foreach ($_POST["db"] as $db) {
|
||||
if (!queries("DROP DATABASE " . idf_escape($db))) {
|
||||
break;
|
||||
|
@ -14,30 +15,32 @@ function connect_error() {
|
|||
queries_redirect(substr(ME, 0, -1), lang('Database has been dropped.'), !$connection->error);
|
||||
}
|
||||
|
||||
page_header(lang('Select database'), $error, null);
|
||||
echo "<p>";
|
||||
page_header(lang('Select database'), $error, false);
|
||||
echo "<p><a href='" . h(ME) . "database='>" . lang('Create new database') . "</a>\n";
|
||||
foreach (array(
|
||||
'database' => lang('Create new database'),
|
||||
'privileges' => lang('Privileges'),
|
||||
'processlist' => lang('Process list'),
|
||||
'variables' => lang('Variables'),
|
||||
'status' => lang('Status'),
|
||||
) as $key => $val) {
|
||||
echo "<a href='" . h(ME) . "$key='>$val</a>\n";
|
||||
if (support($key)) {
|
||||
echo "<a href='" . h(ME) . "$key='>$val</a>\n";
|
||||
}
|
||||
}
|
||||
echo "<p>" . lang('MySQL version: %s through PHP extension %s', "<b" . ($connection->server_info < 4.1 ? " class='binary'" : "") . ">$connection->server_info</b>", "<b>$connection->extension</b>") . "\n";
|
||||
echo "<p>" . lang('Logged as: %s', "<b>" . h($connection->result($connection->query("SELECT USER()"))) . "</b>") . "\n";
|
||||
echo "<p>" . lang('%s version: %s through PHP extension %s', $drivers[DRIVER], "<b>$connection->server_info</b>", "<b>$connection->extension</b>") . "\n";
|
||||
echo "<p>" . lang('Logged as: %s', "<b>" . h(logged_user()) . "</b>") . "\n";
|
||||
$databases = get_databases();
|
||||
if ($databases) {
|
||||
$collations = collations();
|
||||
echo "<form action='' method='post'>\n";
|
||||
echo "<table cellspacing='0' onclick='tableClick(event);'>\n";
|
||||
echo "<thead><tr><td><input type='hidden' name='token' value='$token'> <th>" . lang('Database') . "<td>" . lang('Collation') . "</thead>\n";
|
||||
echo "<thead><tr><td><input type='hidden' name='token' value='$token'> <th>" . lang('Database') . "<td>" . lang('Collation') . "<td>" . lang('Tables') . "</thead>\n";
|
||||
foreach ($databases as $db) {
|
||||
$root = h(ME) . "db=" . urlencode($db);
|
||||
echo "<tr" . odd() . "><td>" . checkbox("db[]", $db, in_array($db, (array) $_POST["db"]));
|
||||
echo "<th><a href='$root'>" . h($db) . "</a>";
|
||||
echo "<td><a href='$root&database='>" . nbsp(db_collation($db, $collations)) . "</a>";
|
||||
echo "<td align='right'><a href='$root&schema=' id='tables-" . h($db) . "'>?</a>";
|
||||
echo "\n";
|
||||
}
|
||||
echo "</table>\n";
|
||||
|
@ -46,6 +49,11 @@ function connect_error() {
|
|||
}
|
||||
}
|
||||
page_footer("db");
|
||||
echo "<script type='text/javascript'>\n";
|
||||
foreach (count_tables($databases) as $db => $val) {
|
||||
echo "setHtml('tables-" . addcslashes($db, "\\'/") . "', '$val');\n";
|
||||
}
|
||||
echo "</script>\n";
|
||||
}
|
||||
|
||||
if (isset($_GET["status"])) {
|
||||
|
@ -53,7 +61,7 @@ if (isset($_GET["status"])) {
|
|||
}
|
||||
if (!(DB != "" ? $connection->select_db(DB) : isset($_GET["sql"]) || isset($_GET["dump"]) || isset($_GET["database"]) || isset($_GET["processlist"]) || isset($_GET["privileges"]) || isset($_GET["user"]) || isset($_GET["variables"]))) {
|
||||
if (DB != "") {
|
||||
unset($_SESSION["databases"][$_GET["server"]]);
|
||||
set_session("databases", null);
|
||||
}
|
||||
connect_error(); // separate function to catch SQLite error
|
||||
exit;
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
<?php
|
||||
/** Print HTML header
|
||||
* @param string used in title, breadcrumb and heading
|
||||
* @param string
|
||||
* @param mixed array("key" => "link=desc", "key2" => array("link", "desc")), null for nothing, false for driver only, true for driver and server
|
||||
* @param string used after colon in title and heading
|
||||
* @return null
|
||||
*/
|
||||
function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") {
|
||||
global $LANG, $VERSION, $adminer, $connection;
|
||||
global $LANG, $VERSION, $adminer, $connection, $drivers;
|
||||
header("Content-Type: text/html; charset=utf-8");
|
||||
header("X-Frame-Options: deny"); // ClickJacking protection in IE8, Safari 4, Chrome 2, NoScript plugin
|
||||
header("X-Frame-Options: deny"); // ClickJacking protection in IE8, Safari 4, Chrome 2, Firefox NoScript plugin
|
||||
$title_all = $title . ($title2 != "" ? ": " . h($title2) : "");
|
||||
?>
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
||||
|
@ -10,34 +17,41 @@ function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") {
|
|||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Script-Type" content="text/javascript">
|
||||
<meta name="robots" content="noindex">
|
||||
<title><?php echo $title_all . ($_GET["server"] != "" && $_GET["server"] != "localhost" ? h(" - $_GET[server]") : "") . " - " . $adminer->name(); ?></title>
|
||||
<title><?php echo $title_all . (SERVER != "" && SERVER != "localhost" ? h(" - " . SERVER) : "") . " - " . $adminer->name(); ?></title>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="../adminer/static/favicon.ico">
|
||||
<link rel="stylesheet" type="text/css" href="../adminer/static/default.css<?php // Ondrej Valka, http://valka.info ?>">
|
||||
<?php if (file_exists("adminer.css")) { ?>
|
||||
<link rel="stylesheet" type="text/css" href="adminer.css">
|
||||
<?php } ?>
|
||||
|
||||
<body onload="bodyLoad('<?php echo substr($connection->server_info, 0, 3); ?>');<?php echo (isset($_COOKIE["adminer_version"]) ? "" : " verifyVersion();"); ?>">
|
||||
<body onload="bodyLoad('<?php echo (is_object($connection) ? substr($connection->server_info, 0, 3) : ""); ?>');<?php echo (isset($_COOKIE["adminer_version"]) ? "" : " verifyVersion();"); ?>">
|
||||
<script type="text/javascript" src="../adminer/static/functions.js"></script>
|
||||
<script type="text/javascript" src="static/editing.js"></script>
|
||||
|
||||
<div id="content">
|
||||
<?php
|
||||
if (isset($breadcrumb)) {
|
||||
$link = substr(preg_replace('~(username|db)=[^&]*&~', '', ME), 0, -1);
|
||||
echo '<p id="breadcrumb"><a href="' . ($link ? h($link) : ".") . '">' . $drivers[DRIVER] . '</a> » ';
|
||||
$link = substr(preg_replace('~db=[^&]*&~', '', ME), 0, -1);
|
||||
echo '<p id="breadcrumb"><a href="' . ($link != "" ? h($link) : ".") . '">' . (isset($_GET["server"]) ? h($_GET["server"]) : lang('Server')) . '</a> » ';
|
||||
if (is_array($breadcrumb)) {
|
||||
if (DB != "") {
|
||||
echo '<a href="' . h(substr(ME, 0, -1)) . '">' . h(DB) . '</a> » ';
|
||||
}
|
||||
foreach ($breadcrumb as $key => $val) {
|
||||
$desc = (is_array($val) ? $val[1] : $val);
|
||||
if ($desc != "") {
|
||||
echo '<a href="' . h(ME . "$key=") . urlencode(is_array($val) ? $val[0] : $val) . '">' . h($desc) . '</a> » ';
|
||||
$server = (SERVER != "" ? h(SERVER) : lang('Server'));
|
||||
if ($breadcrumb === false) {
|
||||
echo "$server\n";
|
||||
} else {
|
||||
echo "<a href='" . ($link ? h($link) : ".") . "'>$server</a> » ";
|
||||
if (is_array($breadcrumb)) {
|
||||
if (DB != "") {
|
||||
echo '<a href="' . h(substr(ME, 0, -1)) . '">' . h(DB) . '</a> » ';
|
||||
}
|
||||
foreach ($breadcrumb as $key => $val) {
|
||||
$desc = (is_array($val) ? $val[1] : $val);
|
||||
if ($desc != "") {
|
||||
echo '<a href="' . h(ME . "$key=") . urlencode(is_array($val) ? $val[0] : $val) . '">' . h($desc) . '</a> » ';
|
||||
}
|
||||
}
|
||||
}
|
||||
echo "$title\n";
|
||||
}
|
||||
echo "$title\n";
|
||||
}
|
||||
echo "<h2>$title_all</h2>\n";
|
||||
restart_session();
|
||||
|
@ -45,10 +59,7 @@ function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") {
|
|||
echo "<div class='message'>" . implode("</div>\n<div class='message'>", $_SESSION["messages"]) . "</div>\n";
|
||||
$_SESSION["messages"] = array();
|
||||
}
|
||||
if (!$_POST && !isset($_SESSION["passwords"])) { // used in auth
|
||||
$_SESSION["passwords"] = array();
|
||||
}
|
||||
$databases = &$_SESSION["databases"][$_GET["server"]];
|
||||
$databases = &get_session("databases");
|
||||
if (DB != "" && $databases && !in_array(DB, $databases, true)) {
|
||||
$databases = null;
|
||||
}
|
||||
|
@ -57,7 +68,11 @@ function page_header($title, $error = "", $breadcrumb = array(), $title2 = "") {
|
|||
}
|
||||
}
|
||||
|
||||
function page_footer($missing = false) {
|
||||
/** Print HTML footer
|
||||
* @param string auth|db
|
||||
* @return null
|
||||
*/
|
||||
function page_footer($missing = "") {
|
||||
global $adminer;
|
||||
?>
|
||||
</div>
|
||||
|
@ -67,4 +82,8 @@ function page_footer($missing = false) {
|
|||
<?php $adminer->navigation($missing); ?>
|
||||
</div>
|
||||
<?php
|
||||
// don't wait for code after footer
|
||||
session_write_close();
|
||||
ob_flush();
|
||||
flush();
|
||||
}
|
||||
|
|
|
@ -84,8 +84,8 @@ function select($result, $connection2 = null) {
|
|||
*/
|
||||
function referencable_primary($self) {
|
||||
$return = array(); // table_name => field
|
||||
foreach (table_status_referencable() as $table_name => $table) {
|
||||
if ($table_name != $self) {
|
||||
foreach (table_status() as $table_name => $table) {
|
||||
if ($table_name != $self && fk_support($table)) {
|
||||
foreach (fields($table_name) as $field) {
|
||||
if ($field["primary"]) {
|
||||
if ($return[$table_name]) { // multi column primary key
|
||||
|
@ -142,16 +142,19 @@ function process_type($field, $collate = "COLLATE") {
|
|||
/** Create SQL string from field
|
||||
* @param array basic field information
|
||||
* @param array information about field type
|
||||
* @return string
|
||||
* @return array array("field", "type", "NULL", "DEFAULT", "ON UPDATE", "COMMENT", "AUTO_INCREMENT")
|
||||
*/
|
||||
function process_field($field, $type_field) {
|
||||
global $connection;
|
||||
return idf_escape($field["field"]) . process_type($type_field)
|
||||
. ($field["null"] ? " NULL" : " NOT NULL") // NULL for timestamp
|
||||
. (!isset($field["default"]) ? "" : " DEFAULT " . ($field["type"] == "timestamp" && eregi("^CURRENT_TIMESTAMP$", $field["default"]) ? $field["default"] : $connection->quote($field["default"])))
|
||||
. ($field["on_update"] ? " ON UPDATE $field[on_update]" : "")
|
||||
. " COMMENT " . $connection->quote($field["comment"])
|
||||
;
|
||||
return array(
|
||||
idf_escape($field["field"]),
|
||||
process_type($type_field),
|
||||
($field["null"] ? " NULL" : " NOT NULL"), // NULL for timestamp
|
||||
(isset($field["default"]) ? " DEFAULT " . ($field["type"] == "timestamp" && eregi("^CURRENT_TIMESTAMP$", $field["default"]) ? $field["default"] : $connection->quote($field["default"])) : ""),
|
||||
($field["on_update"] ? " ON UPDATE $field[on_update]" : ""),
|
||||
(support("comment") && $field["comment"] != "" ? " COMMENT " . $connection->quote($field["comment"]) : ""),
|
||||
($field["auto_increment"] ? auto_increment() : ""),
|
||||
);
|
||||
}
|
||||
|
||||
/** Get type class to use in CSS
|
||||
|
@ -179,12 +182,11 @@ function type_class($type) {
|
|||
* @param array returned by referencable_primary()
|
||||
* @return bool column comments used
|
||||
*/
|
||||
function edit_fields($fields, $collations, $type = "TABLE", $allowed = 0, $foreign_keys = array()) {
|
||||
function edit_fields($fields, $collations, $type = "TABLE", $allowed = 0, $foreign_keys = array(), $comments = false) {
|
||||
global $inout;
|
||||
$column_comments = false;
|
||||
foreach ($fields as $field) {
|
||||
if ($field["comment"] != "") {
|
||||
$column_comments = true;
|
||||
$comments = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -197,9 +199,9 @@ function edit_fields($fields, $collations, $type = "TABLE", $allowed = 0, $forei
|
|||
<td><?php echo lang('Options'); ?>
|
||||
<?php if ($type == "TABLE") { ?>
|
||||
<td>NULL
|
||||
<td><input type="radio" name="auto_increment_col" value=""><acronym title="<?php echo lang('Auto Increment'); ?>">A_I</acronym>
|
||||
<td><input type="radio" name="auto_increment_col" value=""><acronym title="<?php echo lang('Auto Increment'); ?>">AI</acronym>
|
||||
<td class="hidden"><?php echo lang('Default values'); ?>
|
||||
<td<?php echo ($column_comments ? "" : " class='hidden'"); ?>><?php echo lang('Comment'); ?>
|
||||
<?php echo (support("comment") ? "<td" . ($comments ? "" : " class='hidden'") . ">" . lang('Comment') : ""); ?>
|
||||
<?php } ?>
|
||||
<td><?php echo "<input type='image' name='add[0]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "'>"; ?><script type="text/javascript">row_count = <?php echo count($fields); ?>;</script>
|
||||
</thead>
|
||||
|
@ -209,27 +211,24 @@ function edit_fields($fields, $collations, $type = "TABLE", $allowed = 0, $forei
|
|||
$display = (isset($_POST["add"][$i-1]) || (isset($field["field"]) && !$_POST["drop_col"][$i]));
|
||||
?>
|
||||
<tr<?php echo ($display ? "" : " style='display: none;'"); ?>>
|
||||
<?php
|
||||
if ($type == "PROCEDURE") {
|
||||
echo "<td>" . html_select("fields[$i][inout]", $inout, $field["inout"]);
|
||||
}
|
||||
?>
|
||||
<?php echo ($type == "PROCEDURE" ? "<td>" . html_select("fields[$i][inout]", $inout, $field["inout"]) : ""); ?>
|
||||
<th><?php if ($display) { ?><input name="fields[<?php echo $i; ?>][field]" value="<?php echo h($field["field"]); ?>" onchange="<?php echo ($field["field"] != "" || count($fields) > 1 ? "" : "editingAddRow(this, $allowed); "); ?>editingNameChange(this);" maxlength="64"><?php } ?><input type="hidden" name="fields[<?php echo $i; ?>][orig]" value="<?php echo h($field[($_POST ? "orig" : "field")]); ?>">
|
||||
<?php edit_type("fields[$i]", $field, $collations, $foreign_keys); ?>
|
||||
<?php if ($type == "TABLE") { ?>
|
||||
<td><?php echo checkbox("fields[$i][null]", 1, $field["null"]); ?>
|
||||
<td><input type="radio" name="auto_increment_col" value="<?php echo $i; ?>"<?php if ($field["auto_increment"]) { ?> checked<?php } ?>>
|
||||
<td class="hidden"><?php echo checkbox("fields[$i][has_default]", 1, $field["has_default"]); ?><input name="fields[<?php echo $i; ?>][default]" value="<?php echo h($field["default"]); ?>" onchange="this.previousSibling.checked = true;">
|
||||
<td<?php echo ($column_comments ? "" : " class='hidden'"); ?>><input name="fields[<?php echo $i; ?>][comment]" value="<?php echo h($field["comment"]); ?>" maxlength="255">
|
||||
<?php echo (support("comment") ? "<td" . ($comments ? "" : " class='hidden'") . "><input name='fields[$i][comment]' value='" . h($field["comment"]) . "' maxlength='255'>" : ""); ?>
|
||||
<?php } ?>
|
||||
<?php
|
||||
//! hide operations not supported by the driver - column change, adding column not at the end, drop column, ...
|
||||
echo "<td><input type='image' name='add[$i]' src='../adminer/static/plus.gif' alt='+' title='" . lang('Add next') . "' onclick='return !editingAddRow(this, $allowed, 1);'>";
|
||||
echo " <input type='image' name='drop_col[$i]' src='../adminer/static/cross.gif' alt='x' title='" . lang('Remove') . "' onclick='return !editingRemoveRow(this);'>";
|
||||
echo " <input type='image' name='up[$i]' src='../adminer/static/up.gif' alt='^' title='" . lang('Move up') . "'>";
|
||||
echo " <input type='image' name='down[$i]' src='../adminer/static/down.gif' alt='v' title='" . lang('Move down') . "'>";
|
||||
echo "\n";
|
||||
}
|
||||
return $column_comments;
|
||||
return $comments;
|
||||
}
|
||||
|
||||
/** Move fields up and down or add field
|
||||
|
@ -278,7 +277,7 @@ function process_fields(&$fields) {
|
|||
* @return string
|
||||
*/
|
||||
function normalize_enum($match) {
|
||||
return "'" . str_replace("'", "''", addcslashes(stripcslashes(str_replace($match[0]{0} . $match[0]{0}, $match[0]{0}, substr($match[0], 1, -1))), '\\')) . "'";
|
||||
return "'" . str_replace("'", "''", addcslashes(stripcslashes(str_replace($match[0][0] . $match[0][0], $match[0][0], substr($match[0], 1, -1))), '\\')) . "'";
|
||||
}
|
||||
|
||||
/** Get information about stored routine
|
||||
|
@ -291,7 +290,7 @@ function routine($name, $type) {
|
|||
$aliases = array("bit" => "tinyint", "bool" => "tinyint", "boolean" => "tinyint", "integer" => "int", "double precision" => "float", "real" => "float", "dec" => "decimal", "numeric" => "decimal", "fixed" => "decimal", "national char" => "char", "national varchar" => "varchar");
|
||||
$type_pattern = "(" . implode("|", array_keys($types + $aliases)) . ")(?:\\s*\\(((?:[^'\")]*|$enum_length)+)\\))?\\s*(zerofill\\s*)?(unsigned(?:\\s+zerofill)?)?(?:\\s*(?:CHARSET|CHARACTER\\s+SET)\\s*['\"]?([^'\"\\s]+)['\"]?)?";
|
||||
$pattern = "\\s*(" . ($type == "FUNCTION" ? "" : implode("|", $inout)) . ")?\\s*(?:`((?:[^`]|``)*)`\\s*|\\b(\\S+)\\s+)$type_pattern";
|
||||
$create = $connection->result($connection->query("SHOW CREATE $type " . idf_escape($name)), 2);
|
||||
$create = $connection->result("SHOW CREATE $type " . idf_escape($name), 2);
|
||||
preg_match("~\\(((?:$pattern\\s*,?)*)\\)" . ($type == "FUNCTION" ? "\\s*RETURNS\\s+$type_pattern" : "") . "\\s*(.*)~is", $create, $match);
|
||||
$fields = array();
|
||||
preg_match_all("~$pattern\\s*,?~is", $match[1], $matches, PREG_SET_ORDER);
|
||||
|
|
|
@ -11,7 +11,7 @@ function tar_file($filename, $contents) {
|
|||
|
||||
function dump_triggers($table, $style) {
|
||||
global $connection;
|
||||
if ($_POST["format"] == "sql" && $style && $connection->server_info >= 5) {
|
||||
if ($_POST["format"] == "sql" && $style && support("trigger")) {
|
||||
$result = $connection->query("SHOW TRIGGERS LIKE " . $connection->quote(addcslashes($table, "%_")));
|
||||
if ($result->num_rows) {
|
||||
$s = "\nDELIMITER ;;\n";
|
||||
|
@ -26,18 +26,17 @@ function dump_triggers($table, $style) {
|
|||
|
||||
function dump_table($table, $style, $is_view = false) {
|
||||
global $connection;
|
||||
if ($_POST["format"] == "csv") {
|
||||
if ($_POST["format"] != "sql") {
|
||||
echo "\xef\xbb\xbf"; // UTF-8 byte order mark
|
||||
if ($style) {
|
||||
dump_csv(array_keys(fields($table)));
|
||||
}
|
||||
} elseif ($style) {
|
||||
$result = $connection->query("SHOW CREATE TABLE " . idf_escape($table));
|
||||
if ($result) {
|
||||
$create = create_sql($table);
|
||||
if ($create) {
|
||||
if ($style == "DROP+CREATE") {
|
||||
echo "DROP " . ($is_view ? "VIEW" : "TABLE") . " IF EXISTS " . idf_escape($table) . ";\n";
|
||||
}
|
||||
$create = $connection->result($result, 1);
|
||||
echo ($style != "CREATE+ALTER" ? $create : ($is_view ? substr_replace($create, " OR REPLACE", 6, 0) : substr_replace($create, " IF NOT EXISTS", 12, 0))) . ";\n\n";
|
||||
}
|
||||
if ($style == "CREATE+ALTER" && !$is_view) {
|
||||
|
@ -116,10 +115,10 @@ DROP PROCEDURE adminer_alter;
|
|||
}
|
||||
|
||||
function dump_data($table, $style, $select = "") {
|
||||
global $connection;
|
||||
$max_packet = 1048576; // default, minimum is 1024
|
||||
global $connection, $driver;
|
||||
$max_packet = ($driver == "sqlite" ? 0 : 1048576); // default, minimum is 1024
|
||||
if ($style) {
|
||||
if ($_POST["format"] != "csv" && $style == "TRUNCATE+INSERT") {
|
||||
if ($_POST["format"] == "sql" && $style == "TRUNCATE+INSERT") {
|
||||
echo "TRUNCATE " . idf_escape($table) . ";\n";
|
||||
}
|
||||
$fields = fields($table);
|
||||
|
@ -128,7 +127,7 @@ function dump_data($table, $style, $select = "") {
|
|||
$insert = "";
|
||||
$buffer = "";
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
if ($_POST["format"] == "csv") {
|
||||
if ($_POST["format"] != "sql") {
|
||||
dump_csv($row);
|
||||
} else {
|
||||
if (!$insert) {
|
||||
|
@ -145,7 +144,7 @@ function dump_data($table, $style, $select = "") {
|
|||
}
|
||||
echo "$insert ($s) ON DUPLICATE KEY UPDATE " . implode(", ", $set) . ";\n";
|
||||
} else {
|
||||
$s = "\n($s)";
|
||||
$s = ($max_packet ? "\n" : " ") . "($s)";
|
||||
if (!$buffer) {
|
||||
$buffer = $insert . $s;
|
||||
} elseif (strlen($buffer) + 2 + strlen($s) < $max_packet) { // 2 - separator and terminator length
|
||||
|
@ -158,7 +157,7 @@ function dump_data($table, $style, $select = "") {
|
|||
}
|
||||
}
|
||||
}
|
||||
if ($_POST["format"] != "csv" && $style != "INSERT+UPDATE" && $buffer) {
|
||||
if ($_POST["format"] == "sql" && $style != "INSERT+UPDATE" && $buffer) {
|
||||
$buffer .= ";\n";
|
||||
echo $buffer;
|
||||
}
|
||||
|
|
|
@ -8,20 +8,12 @@ function connection() {
|
|||
return $connection;
|
||||
}
|
||||
|
||||
/** Escape database identifier
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function idf_escape($idf) {
|
||||
return "`" . str_replace("`", "``", $idf) . "`";
|
||||
}
|
||||
|
||||
/** Unescape database identifier
|
||||
* @param string text inside ``
|
||||
* @return string
|
||||
*/
|
||||
function idf_unescape($idf) {
|
||||
return str_replace("``", "`", $idf);
|
||||
return str_replace($idf[0] . $idf[0], $idf[0], substr($idf, 1, -1));
|
||||
}
|
||||
|
||||
/** Escape string to use inside ''
|
||||
|
@ -60,6 +52,14 @@ function nbsp($string) {
|
|||
return (trim($string) != "" ? h($string) : " ");
|
||||
}
|
||||
|
||||
/** Convert \n to <br>
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function nl_br($string) {
|
||||
return str_replace("\n", "<br>", $string); // nl2br() uses XHTML before PHP 5.3
|
||||
}
|
||||
|
||||
/** Generate HTML checkbox
|
||||
* @param string
|
||||
* @param string
|
||||
|
@ -71,7 +71,7 @@ function nbsp($string) {
|
|||
function checkbox($name, $value, $checked, $label = "", $onclick = "") {
|
||||
static $id = 0;
|
||||
$id++;
|
||||
$return = "<input type='checkbox' name='$name' value='" . h($value) . "'" . ($checked ? " checked" : "") . ($onclick ? " onclick=\"$onclick\"" : "") . " id='checkbox-$id'>";
|
||||
$return = "<input type='checkbox'" . ($name ? " name='$name' value='" . h($value) . "'" : "") . ($checked ? " checked" : "") . ($onclick ? " onclick=\"$onclick\"" : "") . " id='checkbox-$id'>";
|
||||
return ($label != "" ? "<label for='checkbox-$id'>$return" . h($label) . "</label>" : $return);
|
||||
}
|
||||
|
||||
|
@ -115,6 +115,15 @@ function html_select($name, $options, $value = "", $onchange = true) {
|
|||
return $return;
|
||||
}
|
||||
|
||||
/** Get INI boolean value
|
||||
* @param string
|
||||
* @return bool
|
||||
*/
|
||||
function ini_bool($ini) {
|
||||
$val = ini_get($ini);
|
||||
return (eregi('^(on|true|yes)$', $val) || (int) $val); // boolean values set by php_value are strings
|
||||
}
|
||||
|
||||
/** Get list of values from database
|
||||
* @param string
|
||||
* @param mixed
|
||||
|
@ -132,6 +141,24 @@ function get_vals($query, $column = 0) {
|
|||
return $return;
|
||||
}
|
||||
|
||||
/** Get keys from first column and values from second
|
||||
* @param string
|
||||
* @param Min_DB
|
||||
* @return array
|
||||
*/
|
||||
function get_key_vals($query, $connection2 = null) {
|
||||
global $connection;
|
||||
if (!is_object($connection2)) {
|
||||
$connection2 = $connection;
|
||||
}
|
||||
$return = array();
|
||||
$result = $connection2->query($query);
|
||||
while ($row = $result->fetch_row()) {
|
||||
$return[$row[0]] = $row[1];
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Find unique identifier of a row
|
||||
* @param array
|
||||
* @param array result of indexes()
|
||||
|
@ -200,7 +227,14 @@ function where_link($i, $column, $value, $operator = "=") {
|
|||
* @return bool
|
||||
*/
|
||||
function cookie($name, $value) {
|
||||
$params = array($name, $value, time() + 2592000, preg_replace('~\\?.*~', '', $_SERVER["REQUEST_URI"]), "", $_SERVER["HTTPS"] && strcasecmp($_SERVER["HTTPS"], "off")); // 2592000 = 30 * 24 * 60 * 60
|
||||
$params = array(
|
||||
$name,
|
||||
(ereg("\n", $value) ? "" : $value), // HTTP Response Splitting protection in PHP < 5.1.2
|
||||
time() + 2592000, // 2592000 - 30 days
|
||||
preg_replace('~\\?.*~', '', $_SERVER["REQUEST_URI"]),
|
||||
"",
|
||||
$_SERVER["HTTPS"] && strcasecmp($_SERVER["HTTPS"], "off")
|
||||
);
|
||||
if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
|
||||
$params[] = true; // HttpOnly
|
||||
}
|
||||
|
@ -211,11 +245,28 @@ function cookie($name, $value) {
|
|||
* @return null
|
||||
*/
|
||||
function restart_session() {
|
||||
if (!ini_get("session.use_cookies")) {
|
||||
if (!ini_bool("session.use_cookies")) {
|
||||
session_start();
|
||||
}
|
||||
}
|
||||
|
||||
/** Get session variable for current server
|
||||
* @param string
|
||||
* @return mixed
|
||||
*/
|
||||
function &get_session($key) {
|
||||
return $_SESSION[$key][DRIVER][SERVER][$_GET["username"]];
|
||||
}
|
||||
|
||||
/** Set session variable for current server
|
||||
* @param string
|
||||
* @param mixed
|
||||
* @return mixed
|
||||
*/
|
||||
function set_session($key, $val) {
|
||||
$_SESSION[$key][DRIVER][SERVER][$_GET["username"]] = $val; // used also in auth.inc.php
|
||||
}
|
||||
|
||||
/** Send Location header and exit
|
||||
* @param string null to only set a message
|
||||
* @param string
|
||||
|
@ -385,6 +436,15 @@ function hidden_fields($process, $ignore = array()) {
|
|||
}
|
||||
}
|
||||
|
||||
/** Print hidden fields for GET forms
|
||||
* @return null
|
||||
*/
|
||||
function hidden_fields_get() {
|
||||
echo (SID && !$_COOKIE ? '<input type="hidden" name="' . session_name() . '" value="' . h(session_id()) . '">' : '');
|
||||
echo (SERVER !== null ? '<input type="hidden" name="' . DRIVER . '" value="' . h(SERVER) . '">' : "");
|
||||
echo '<input type="hidden" name="username" value="' . h($_GET["username"]) . '">';
|
||||
}
|
||||
|
||||
/** Find out foreign keys for each column
|
||||
* @param string
|
||||
* @return array array($col => array())
|
||||
|
@ -399,6 +459,22 @@ function column_foreign_keys($table) {
|
|||
return $return;
|
||||
}
|
||||
|
||||
/** Print enum input field
|
||||
* @param string "radio"|"checkbox"
|
||||
* @param string
|
||||
* @param array
|
||||
* @param mixed int|string|array
|
||||
* @return null
|
||||
*/
|
||||
function enum_input($type, $name, $field, $value) {
|
||||
preg_match_all("~'((?:[^']|'')*)'~", $field["length"], $matches);
|
||||
foreach ($matches[1] as $i => $val) {
|
||||
$val = stripcslashes(str_replace("''", "'", $val));
|
||||
$checked = (is_int($value) ? $value == $i+1 : (is_array($value) ? in_array($i+1, $value) : $value === $val));
|
||||
echo " <label><input type='$type' name='$name' value='" . ($i+1) . "'" . ($checked ? ' checked' : '') . '>' . h($val) . '</label>';
|
||||
}
|
||||
}
|
||||
|
||||
/** Print edit input field
|
||||
* @param array one field from fields()
|
||||
* @param mixed
|
||||
|
@ -406,19 +482,14 @@ function column_foreign_keys($table) {
|
|||
* @return null
|
||||
*/
|
||||
function input($field, $value, $function) {
|
||||
global $types, $adminer;
|
||||
global $types, $adminer, $driver;
|
||||
$name = h(bracket_escape($field["field"]));
|
||||
echo "<td class='function'>";
|
||||
$functions = (isset($_GET["select"]) ? array("orig" => lang('original')) : array()) + $adminer->editFunctions($field);
|
||||
if ($field["type"] == "enum") {
|
||||
echo nbsp($functions[""]) . "<td>" . ($functions["orig"] ? "<label><input type='radio' name='fields[$name]' value='-1' checked><em>$functions[orig]</em></label> " : "");
|
||||
echo $adminer->editInput($_GET["edit"], $field, " name='fields[$name]'", $value);
|
||||
preg_match_all("~'((?:[^']|'')*)'~", $field["length"], $matches);
|
||||
foreach ($matches[1] as $i => $val) {
|
||||
$val = stripcslashes(str_replace("''", "'", $val));
|
||||
$checked = (is_int($value) ? $value == $i+1 : $value === $val);
|
||||
echo " <label><input type='radio' name='fields[$name]' value='" . ($i+1) . "'" . ($checked ? ' checked' : '') . '>' . h($val) . '</label>';
|
||||
}
|
||||
enum_input("radio", "fields[$name]", $field, $value);
|
||||
} else {
|
||||
$first = 0;
|
||||
foreach ($functions as $key => $val) {
|
||||
|
@ -440,10 +511,10 @@ function input($field, $value, $function) {
|
|||
$checked = (is_int($value) ? ($value >> $i) & 1 : in_array($val, explode(",", $value), true));
|
||||
echo " <label><input type='checkbox' name='fields[$name][$i]' value='" . (1 << $i) . "'" . ($checked ? ' checked' : '') . "$onchange>" . h($val) . '</label>';
|
||||
}
|
||||
} elseif (ereg('binary|blob', $field["type"]) && ini_get("file_uploads")) {
|
||||
} elseif (ereg('binary|blob|bytea', $field["type"]) && ini_bool("file_uploads")) {
|
||||
echo "<input type='file' name='fields-$name'$onchange>";
|
||||
} elseif (ereg('text|blob', $field["type"])) {
|
||||
echo "<textarea cols='50' rows='12'$attrs>" . h($value) . '</textarea>';
|
||||
echo "<textarea cols='50' rows='" . ($driver != "sqlite" || ereg("\n", $value) ? 12 : 1) . "'$attrs>" . h($value) . '</textarea>';
|
||||
} else {
|
||||
// int(3) is only a display hint
|
||||
$maxlength = (!ereg('int', $field["type"]) && preg_match('~^([0-9]+)(,([0-9]+))?$~', $field["length"], $match) ? ($match[1] + ($match[3] ? 1 : 0) + ($match[2] && !$field["unsigned"] ? 1 : 0)) : ($types[$field["type"]] ? $types[$field["type"]] + ($field["unsigned"] ? 0 : 1) : 0));
|
||||
|
@ -461,23 +532,35 @@ function process_input($field) {
|
|||
$idf = bracket_escape($field["field"]);
|
||||
$function = $_POST["function"][$idf];
|
||||
$value = $_POST["fields"][$idf];
|
||||
if ($field["type"] == "enum" ? $value == -1 : $function == "orig") {
|
||||
return false;
|
||||
} elseif ($field["type"] == "enum" || $field["auto_increment"] ? $value == "" : $function == "NULL") {
|
||||
return "NULL";
|
||||
} elseif ($field["type"] == "enum") {
|
||||
if ($field["type"] == "enum") {
|
||||
if ($value == -1) {
|
||||
return false;
|
||||
}
|
||||
if ($value == "") {
|
||||
return "NULL";
|
||||
}
|
||||
return intval($value);
|
||||
} elseif ($field["type"] == "set") {
|
||||
}
|
||||
if ($field["auto_increment"] && $value == "") {
|
||||
return null;
|
||||
}
|
||||
if ($function == "orig") {
|
||||
return false;
|
||||
}
|
||||
if ($function == "NULL") {
|
||||
return "NULL";
|
||||
}
|
||||
if ($field["type"] == "set") {
|
||||
return array_sum((array) $value);
|
||||
} elseif (ereg('binary|blob', $field["type"]) && ini_get("file_uploads")) {
|
||||
}
|
||||
if (ereg('binary|blob|bytea', $field["type"]) && ini_bool("file_uploads")) {
|
||||
$file = get_file("fields-$idf");
|
||||
if (!is_string($file)) {
|
||||
return false; //! report errors
|
||||
}
|
||||
return $connection->quote($file);
|
||||
} else {
|
||||
return $adminer->processInput($field, $value, $function);
|
||||
}
|
||||
return $adminer->processInput($field, $value, $function);
|
||||
}
|
||||
|
||||
/** Print results of search in all tables
|
||||
|
@ -491,7 +574,7 @@ function search_tables() {
|
|||
foreach (table_status() as $table => $table_status) {
|
||||
$name = $adminer->tableName($table_status);
|
||||
if (isset($table_status["Engine"]) && $name != "" && (!$_POST["tables"] || in_array($table, $_POST["tables"]))) {
|
||||
$result = $connection->query("SELECT 1 FROM " . idf_escape($table) . " WHERE " . implode(" AND ", $adminer->selectSearchProcess(fields($table), array())) . " LIMIT 1");
|
||||
$result = $connection->query("SELECT" . limit("1 FROM " . idf_escape($table) . " WHERE " . implode(" AND ", $adminer->selectSearchProcess(fields($table), array())), 1));
|
||||
if ($result->num_rows) {
|
||||
if (!$found) {
|
||||
echo "<ul>\n";
|
||||
|
@ -510,11 +593,11 @@ function search_tables() {
|
|||
*/
|
||||
function dump_csv($row) {
|
||||
foreach ($row as $key => $val) {
|
||||
if (preg_match("~[\"\n,]~", $val) || $val === "") {
|
||||
if (preg_match("~[\"\n,;]~", $val) || $val === "") {
|
||||
$row[$key] = '"' . str_replace('"', '""', $val) . '"';
|
||||
}
|
||||
}
|
||||
echo implode(",", $row) . "\n";
|
||||
echo implode(($_POST["format"] == "csv;" ? ";" : ","), $row) . "\n";
|
||||
}
|
||||
|
||||
/** Apply SQL function
|
||||
|
@ -523,7 +606,7 @@ function dump_csv($row) {
|
|||
* @return string
|
||||
*/
|
||||
function apply_sql_function($function, $column) {
|
||||
return ($function ? ($function == "count distinct" ? "COUNT(DISTINCT " : strtoupper("$function(")) . "$column)" : $column);
|
||||
return ($function ? ($function == "unixepoch" ? "DATETIME($column, '$function')" : ($function == "count distinct" ? "COUNT(DISTINCT " : strtoupper("$function(")) . "$column)") : $column);
|
||||
}
|
||||
|
||||
/** Check whether the string is e-mail address
|
||||
|
|
|
@ -1,406 +0,0 @@
|
|||
<?php
|
||||
// MySQLi supports everything, MySQL doesn't support multiple result sets, PDO_MySQL doesn't support orgtable
|
||||
if (extension_loaded("mysqli")) {
|
||||
class Min_DB extends MySQLi {
|
||||
var $extension = "MySQLi";
|
||||
|
||||
function Min_DB() {
|
||||
parent::init();
|
||||
}
|
||||
|
||||
function connect($server, $username, $password) {
|
||||
list($host, $port) = explode(":", $server, 2); // part after : is used for port or socket
|
||||
return @$this->real_connect(
|
||||
($server != "" ? $host : ini_get("mysqli.default_host")),
|
||||
("$server$username" != "" ? $username : ini_get("mysqli.default_user")),
|
||||
("$server$username$password" != "" ? $password : ini_get("mysqli.default_pw")),
|
||||
null,
|
||||
(is_numeric($port) ? $port : ini_get("mysqli.default_port")),
|
||||
(!is_numeric($port) ? $port : null)
|
||||
);
|
||||
}
|
||||
|
||||
function result($result, $field = 0) {
|
||||
if (!$result) {
|
||||
return false;
|
||||
}
|
||||
$row = $result->fetch_array();
|
||||
return $row[$field];
|
||||
}
|
||||
|
||||
function quote($string) {
|
||||
return "'" . $this->escape_string($string) . "'";
|
||||
}
|
||||
}
|
||||
|
||||
} elseif (extension_loaded("mysql")) {
|
||||
class Min_DB {
|
||||
var $extension = "MySQL", $_link, $_result, $server_info, $affected_rows, $error;
|
||||
|
||||
function connect($server, $username, $password) {
|
||||
$this->_link = @mysql_connect(
|
||||
($server != "" ? $server : ini_get("mysql.default_host")),
|
||||
("$server$username" != "" ? $username : ini_get("mysql.default_user")),
|
||||
("$server$username$password" != "" ? $password : ini_get("mysql.default_password")),
|
||||
true,
|
||||
131072 // CLIENT_MULTI_RESULTS for CALL
|
||||
);
|
||||
if ($this->_link) {
|
||||
$this->server_info = mysql_get_server_info($this->_link);
|
||||
} else {
|
||||
$this->error = mysql_error();
|
||||
}
|
||||
return (bool) $this->_link;
|
||||
}
|
||||
|
||||
function quote($string) {
|
||||
return "'" . mysql_real_escape_string($string, $this->_link) . "'";
|
||||
}
|
||||
|
||||
function select_db($database) {
|
||||
return mysql_select_db($database, $this->_link);
|
||||
}
|
||||
|
||||
function query($query, $unbuffered = false) {
|
||||
$result = @($unbuffered ? mysql_unbuffered_query($query, $this->_link) : mysql_query($query, $this->_link)); // @ - mute mysql.trace_mode
|
||||
if (!$result) {
|
||||
$this->error = mysql_error($this->_link);
|
||||
return false;
|
||||
}
|
||||
if ($result === true) {
|
||||
$this->affected_rows = mysql_affected_rows($this->_link);
|
||||
$this->info = mysql_info($this->_link);
|
||||
return true;
|
||||
}
|
||||
return new Min_Result($result);
|
||||
}
|
||||
|
||||
function multi_query($query) {
|
||||
return $this->_result = $this->query($query);
|
||||
}
|
||||
|
||||
function store_result() {
|
||||
return $this->_result;
|
||||
}
|
||||
|
||||
function next_result() {
|
||||
// MySQL extension doesn't support multiple results
|
||||
return false;
|
||||
}
|
||||
|
||||
function result($result, $field = 0) {
|
||||
if (!$result) {
|
||||
return false;
|
||||
}
|
||||
return mysql_result($result->_result, 0, $field);
|
||||
}
|
||||
}
|
||||
|
||||
class Min_Result {
|
||||
var $_result, $_offset = 0, $num_rows;
|
||||
|
||||
function Min_Result($result) {
|
||||
$this->_result = $result;
|
||||
$this->num_rows = mysql_num_rows($result);
|
||||
}
|
||||
|
||||
function fetch_assoc() {
|
||||
return mysql_fetch_assoc($this->_result);
|
||||
}
|
||||
|
||||
function fetch_row() {
|
||||
return mysql_fetch_row($this->_result);
|
||||
}
|
||||
|
||||
function fetch_field() {
|
||||
$row = mysql_fetch_field($this->_result, $this->_offset++);
|
||||
$row->orgtable = $row->table;
|
||||
$row->orgname = $row->name;
|
||||
$row->charsetnr = ($row->blob ? 63 : 0);
|
||||
return $row;
|
||||
}
|
||||
|
||||
function __destruct() {
|
||||
mysql_free_result($this->_result); //! is not called in PHP 4 which is a problem with mysql.trace_mode
|
||||
}
|
||||
}
|
||||
|
||||
} elseif (extension_loaded("pdo_mysql")) {
|
||||
class Min_DB extends Min_PDO {
|
||||
var $extension = "PDO_MySQL";
|
||||
|
||||
function connect($server, $username, $password) {
|
||||
$this->dsn("mysql:host=" . str_replace(":", ";unix_socket=", preg_replace('~:([0-9])~', ';port=\\1', $server)), $username, $password);
|
||||
$this->server_info = $this->result($this->query("SELECT VERSION()"));
|
||||
return true;
|
||||
}
|
||||
|
||||
function query($query, $unbuffered = false) {
|
||||
$this->setAttribute(1000, !$unbuffered); // 1000 - PDO::MYSQL_ATTR_USE_BUFFERED_QUERY
|
||||
return parent::query($query, $unbuffered);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
page_header(lang('No MySQL extension'), lang('None of the supported PHP extensions (%s) are available.', 'MySQLi, MySQL, PDO_MySQL'), null);
|
||||
page_footer("auth");
|
||||
exit;
|
||||
}
|
||||
|
||||
/** Connect to the database
|
||||
* @return mixed Min_DB or string for error
|
||||
*/
|
||||
function connect() {
|
||||
global $adminer;
|
||||
$connection = new Min_DB;
|
||||
$credentials = $adminer->credentials();
|
||||
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
|
||||
$connection->query("SET SQL_QUOTE_SHOW_CREATE=1");
|
||||
$connection->query("SET NAMES utf8");
|
||||
return $connection;
|
||||
}
|
||||
return $connection->error;
|
||||
}
|
||||
|
||||
/** Get cached list of databases
|
||||
* @param bool
|
||||
* @return array
|
||||
*/
|
||||
function get_databases($flush = true) {
|
||||
// SHOW DATABASES can take a very long time so it is cached
|
||||
$return = &$_SESSION["databases"][$_GET["server"]];
|
||||
if (!isset($return)) {
|
||||
restart_session();
|
||||
$return = get_vals("SHOW DATABASES");
|
||||
if ($flush) {
|
||||
ob_flush();
|
||||
flush();
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Get database collation
|
||||
* @param string
|
||||
* @param array result of collations()
|
||||
* @return array
|
||||
*/
|
||||
function db_collation($db, $collations) {
|
||||
global $connection;
|
||||
$return = null;
|
||||
$result = $connection->query("SHOW CREATE DATABASE " . idf_escape($db));
|
||||
if ($result) {
|
||||
$create = $connection->result($result, 1);
|
||||
if (preg_match('~ COLLATE ([^ ]+)~', $create, $match)) {
|
||||
$return = $match[1];
|
||||
} elseif (preg_match('~ CHARACTER SET ([^ ]+)~', $create, $match)) {
|
||||
// default collation
|
||||
$return = $collations[$match[1]][0];
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**Get supported engines
|
||||
* @return array
|
||||
*/
|
||||
function engines() {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SHOW ENGINES");
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
if (ereg("YES|DEFAULT", $row["Support"])) {
|
||||
$return[] = $row["Engine"];
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Get tables list
|
||||
* @return array
|
||||
*/
|
||||
function tables_list() {
|
||||
return get_vals("SHOW TABLES");
|
||||
}
|
||||
|
||||
/** Get table status
|
||||
* @param string
|
||||
* @return array
|
||||
*/
|
||||
function table_status($name = "") {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SHOW TABLE STATUS" . ($name != "" ? " LIKE " . $connection->quote(addcslashes($name, "%_")) : ""));
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
if ($row["Engine"] == "InnoDB") {
|
||||
// ignore internal comment, unnecessary since MySQL 5.1.21
|
||||
$row["Comment"] = preg_replace('~(?:(.+); )?InnoDB free: .*~', '\\1', $row["Comment"]);
|
||||
}
|
||||
if ($name != "") {
|
||||
return $row;
|
||||
}
|
||||
$return[$row["Name"]] = $row;
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Get status of referencable tables
|
||||
* @return array
|
||||
*/
|
||||
function table_status_referencable() {
|
||||
$return = array();
|
||||
foreach (table_status() as $name => $row) {
|
||||
if ($row["Engine"] == "InnoDB") {
|
||||
$return[$name] = $row;
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Get information about fields
|
||||
* @param string
|
||||
* @return array array($name => array("field" => , "full_type" => , "type" => , "length" => , "unsigned" => , "default" => , "null" => , "auto_increment" => , "on_update" => , "collation" => , "privileges" => , "comment" => , "primary" => ))
|
||||
*/
|
||||
function fields($table) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SHOW FULL COLUMNS FROM " . idf_escape($table));
|
||||
if ($result) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
preg_match('~^([^( ]+)(?:\\((.+)\\))?( unsigned)?( zerofill)?$~', $row["Type"], $match);
|
||||
$return[$row["Field"]] = array(
|
||||
"field" => $row["Field"],
|
||||
"full_type" => $row["Type"],
|
||||
"type" => $match[1],
|
||||
"length" => $match[2],
|
||||
"unsigned" => ltrim($match[3] . $match[4]),
|
||||
"default" => ($row["Default"] != "" || ereg("char", $match[1]) ? $row["Default"] : null),
|
||||
"null" => ($row["Null"] == "YES"),
|
||||
"auto_increment" => ($row["Extra"] == "auto_increment"),
|
||||
"on_update" => (eregi('^on update (.+)', $row["Extra"], $match) ? $match[1] : ""), //! available since MySQL 5.1.23
|
||||
"collation" => $row["Collation"],
|
||||
"privileges" => array_flip(explode(",", $row["Privileges"])),
|
||||
"comment" => $row["Comment"],
|
||||
"primary" => ($row["Key"] == "PRI"),
|
||||
);
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Get table indexes
|
||||
* @param string
|
||||
* @param string Min_DB to use
|
||||
* @return array array($key_name => array("type" => , "columns" => array(), "lengths" => array()))
|
||||
*/
|
||||
function indexes($table, $connection2 = null) {
|
||||
global $connection;
|
||||
if (!is_object($connection2)) { // use the main connection if the separate connection is unavailable
|
||||
$connection2 = $connection;
|
||||
}
|
||||
$return = array();
|
||||
$result = $connection2->query("SHOW INDEX FROM " . idf_escape($table));
|
||||
if ($result) {
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["Key_name"]]["type"] = ($row["Key_name"] == "PRIMARY" ? "PRIMARY" : ($row["Index_type"] == "FULLTEXT" ? "FULLTEXT" : ($row["Non_unique"] ? "INDEX" : "UNIQUE")));
|
||||
$return[$row["Key_name"]]["columns"][$row["Seq_in_index"]] = $row["Column_name"];
|
||||
$return[$row["Key_name"]]["lengths"][$row["Seq_in_index"]] = $row["Sub_part"];
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Get foreign keys in table
|
||||
* @param string
|
||||
* @return array array($name => array("db" => , "table" => , "source" => array(), "target" => array(), "on_delete" => , "on_update" => ))
|
||||
*/
|
||||
function foreign_keys($table) {
|
||||
global $connection, $on_actions;
|
||||
static $pattern = '(?:[^`]|``)+';
|
||||
$return = array();
|
||||
$result = $connection->query("SHOW CREATE TABLE " . idf_escape($table));
|
||||
if ($result) {
|
||||
$create_table = $connection->result($result, 1);
|
||||
preg_match_all("~CONSTRAINT `($pattern)` FOREIGN KEY \\(((?:`$pattern`,? ?)+)\\) REFERENCES `($pattern)`(?:\\.`($pattern)`)? \\(((?:`$pattern`,? ?)+)\\)(?: ON DELETE (" . implode("|", $on_actions) . "))?(?: ON UPDATE (" . implode("|", $on_actions) . "))?~", $create_table, $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $match) {
|
||||
preg_match_all("~`($pattern)`~", $match[2], $source);
|
||||
preg_match_all("~`($pattern)`~", $match[5], $target);
|
||||
$return[$match[1]] = array(
|
||||
"db" => idf_unescape($match[4] != "" ? $match[3] : $match[4]),
|
||||
"table" => idf_unescape($match[4] != "" ? $match[4] : $match[3]),
|
||||
"source" => array_map('idf_unescape', $source[1]),
|
||||
"target" => array_map('idf_unescape', $target[1]),
|
||||
"on_delete" => $match[6],
|
||||
"on_update" => $match[7],
|
||||
);
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Get view SELECT
|
||||
* @param string
|
||||
* @return array array("select" => )
|
||||
*/
|
||||
function view($name) {
|
||||
global $connection;
|
||||
return array("select" => preg_replace('~^(?:[^`]|`[^`]*`)* AS ~U', '', $connection->result($connection->query("SHOW CREATE VIEW " . idf_escape($name)), 1)));
|
||||
}
|
||||
|
||||
/** Get sorted grouped list of collations
|
||||
* @return array
|
||||
*/
|
||||
function collations() {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query("SHOW COLLATION");
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["Charset"]][] = $row["Collation"];
|
||||
}
|
||||
ksort($return);
|
||||
foreach ($return as $key => $val) {
|
||||
sort($return[$key]);
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
/** Find out if database is information_schema
|
||||
* @param string
|
||||
* @return bool
|
||||
*/
|
||||
function information_schema($db) {
|
||||
global $connection;
|
||||
return ($connection->server_info >= 5 && $db == "information_schema");
|
||||
}
|
||||
|
||||
/** Get escaped error message
|
||||
* @return string
|
||||
*/
|
||||
function error() {
|
||||
global $connection;
|
||||
return h(preg_replace('~^You have an error.*syntax to use~U', "Syntax error", $connection->error));
|
||||
}
|
||||
|
||||
/** Return expression for binary comparison
|
||||
* @param string
|
||||
* @return string
|
||||
*/
|
||||
function exact_value($val) {
|
||||
global $connection;
|
||||
return "BINARY " . $connection->quote($val);
|
||||
}
|
||||
|
||||
// value means maximum unsigned length
|
||||
$types = array();
|
||||
$structured_types = array();
|
||||
foreach (array(
|
||||
lang('Numbers') => array("tinyint" => 3, "smallint" => 5, "mediumint" => 8, "int" => 10, "bigint" => 20, "decimal" => 66, "float" => 12, "double" => 21),
|
||||
lang('Date and time') => array("date" => 10, "datetime" => 19, "timestamp" => 19, "time" => 10, "year" => 4),
|
||||
lang('Strings') => array("char" => 255, "varchar" => 65535, "tinytext" => 255, "text" => 65535, "mediumtext" => 16777215, "longtext" => 4294967295),
|
||||
lang('Binary') => array("binary" => 255, "varbinary" => 65535, "tinyblob" => 255, "blob" => 65535, "mediumblob" => 16777215, "longblob" => 4294967295),
|
||||
lang('Lists') => array("enum" => 65535, "set" => 64),
|
||||
) as $key => $val) {
|
||||
$types += $val;
|
||||
$structured_types[$key] = array_keys($val);
|
||||
}
|
||||
$unsigned = array("unsigned", "zerofill", "unsigned zerofill");
|
|
@ -1,23 +1,21 @@
|
|||
<?php
|
||||
// PDO can be used in several database drivers
|
||||
if (extension_loaded('pdo')) {
|
||||
class Min_PDO extends PDO {
|
||||
/*abstract */class Min_PDO extends PDO {
|
||||
var $_result, $server_info, $affected_rows, $error;
|
||||
|
||||
function __construct() {
|
||||
}
|
||||
|
||||
function dsn($dsn, $username, $password) {
|
||||
set_exception_handler('auth_error'); // try/catch is not compatible with PHP 4
|
||||
function dsn($dsn, $username, $password, $exception_handler = 'auth_error') {
|
||||
set_exception_handler($exception_handler); // try/catch is not compatible with PHP 4
|
||||
parent::__construct($dsn, $username, $password);
|
||||
restore_exception_handler();
|
||||
$this->setAttribute(13, array('Min_PDOStatement')); // PDO::ATTR_STATEMENT_CLASS
|
||||
$this->setAttribute(13, array('Min_PDOStatement')); // 13 - PDO::ATTR_STATEMENT_CLASS
|
||||
$this->server_info = $this->getAttribute(4); // 4 - PDO::ATTR_SERVER_VERSION
|
||||
}
|
||||
|
||||
function select_db($database) {
|
||||
// database selection is separated from the connection so dbname in DSN can't be used
|
||||
return $this->query("USE " . idf_escape($database));
|
||||
}
|
||||
/*abstract function select_db($database);*/
|
||||
|
||||
function query($query, $unbuffered = false) {
|
||||
$result = parent::query($query);
|
||||
|
@ -50,7 +48,8 @@ if (extension_loaded('pdo')) {
|
|||
return $this->_result->nextRowset();
|
||||
}
|
||||
|
||||
function result($result, $field = 0) {
|
||||
function result($query, $field = 0) {
|
||||
$result = $this->query($query);
|
||||
if (!$result) {
|
||||
return false;
|
||||
}
|
||||
|
@ -79,3 +78,6 @@ if (extension_loaded('pdo')) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
$possible_drivers = array();
|
||||
$drivers = array();
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
<?php
|
||||
$VERSION = "2.3.2";
|
||||
$VERSION = "3.0.0-dev";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
/** Adminer - Compact MySQL management
|
||||
/** Adminer - Compact database management
|
||||
* @link http://www.adminer.org/
|
||||
* @author Jakub Vrana, http://php.vrana.cz/
|
||||
* @copyright 2007 Jakub Vrana
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
<?php
|
||||
$TABLE = $_GET["indexes"];
|
||||
$index_types = array("PRIMARY", "UNIQUE", "INDEX", "FULLTEXT");
|
||||
$index_types = array("PRIMARY", "UNIQUE", "INDEX");
|
||||
$table_status = table_status($TABLE);
|
||||
if (ereg("MyISAM|Maria", $table_status["Engine"])) {
|
||||
$index_types[] = "FULLTEXT";
|
||||
}
|
||||
$indexes = indexes($TABLE);
|
||||
if ($_POST && !$error && !$_POST["add"]) {
|
||||
$alter = array();
|
||||
|
@ -14,32 +18,32 @@ if ($_POST && !$error && !$_POST["add"]) {
|
|||
if ($column != "") {
|
||||
$length = $index["lengths"][$key];
|
||||
$set[] = idf_escape($column) . ($length ? "(" . intval($length) . ")" : "");
|
||||
$columns[count($columns) + 1] = $column;
|
||||
$lengths[count($lengths) + 1] = ($length ? $length : null);
|
||||
$columns[] = $column;
|
||||
$lengths[] = ($length ? $length : null);
|
||||
}
|
||||
}
|
||||
if ($columns) {
|
||||
foreach ($indexes as $name => $existing) {
|
||||
ksort($existing["columns"]);
|
||||
ksort($existing["lengths"]);
|
||||
if ($index["type"] == $existing["type"] && $existing["columns"] === $columns && $existing["lengths"] === $lengths) {
|
||||
if ($index["type"] == $existing["type"] && array_values($existing["columns"]) === $columns && (!$existing["lengths"] || array_values($existing["lengths"]) === $lengths)) {
|
||||
// skip existing index
|
||||
unset($indexes[$name]);
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
$alter[] = "\nADD $index[type]" . ($index["type"] == "PRIMARY" ? " KEY" : "") . " (" . implode(", ", $set) . ")";
|
||||
$alter[] = array($index["type"], "(" . implode(", ", $set) . ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
// drop removed indexes
|
||||
foreach ($indexes as $name => $existing) {
|
||||
$alter[] = "\nDROP INDEX " . idf_escape($name);
|
||||
$alter[] = array($existing["type"], idf_escape($name), "DROP");
|
||||
}
|
||||
if (!$alter) {
|
||||
redirect(ME . "table=" . urlencode($TABLE));
|
||||
}
|
||||
query_redirect("ALTER TABLE " . idf_escape($TABLE) . implode(",", $alter), ME . "table=" . urlencode($TABLE), lang('Indexes have been altered.'));
|
||||
queries_redirect(ME . "table=" . urlencode($TABLE), lang('Indexes have been altered.'), alter_indexes($TABLE, $alter));
|
||||
}
|
||||
|
||||
page_header(lang('Indexes'), $error, array("table" => $TABLE), $TABLE);
|
||||
|
@ -77,7 +81,7 @@ foreach ($row["indexes"] as $index) {
|
|||
ksort($index["columns"]);
|
||||
foreach ($index["columns"] as $i => $column) {
|
||||
echo "<span>" . html_select("indexes[$j][columns][$i]", array(-1 => "") + $fields, $column, ($i == count($index["columns"]) ? "indexesAddColumn(this);" : 1));
|
||||
echo "<input name='indexes[$j][lengths][$i]' size='2' value='" . h($index["lengths"][$i]) . "'> </span>\n";
|
||||
echo "<input name='indexes[$j][lengths][$i]' size='2' value='" . h($index["lengths"][$i]) . "'> </span>\n"; //! hide for non-MySQL drivers, add ASC|DESC
|
||||
}
|
||||
echo "\n";
|
||||
$j++;
|
||||
|
|
|
@ -81,7 +81,7 @@ $translations = array(
|
|||
'File uploads are disabled.' => 'Nahrávání souborů není povoleno.',
|
||||
'Routine has been called, %d row(s) affected.' => array('Procedura byla zavolána, byl změněn %d záznam.', 'Procedura byla zavolána, byly změněny %d záznamy.', 'Procedura byla zavolána, bylo změněno %d záznamů.'),
|
||||
'Call' => 'Zavolat',
|
||||
'No MySQL extension' => 'Žádná MySQL extenze',
|
||||
'No extension' => 'Žádná extenze',
|
||||
'None of the supported PHP extensions (%s) are available.' => 'Není dostupná žádná z podporovaných PHP extenzí (%s).',
|
||||
'Session support must be enabled.' => 'Session proměnné musí být povolené.',
|
||||
'Session expired, please login again.' => 'Session vypršela, přihlašte se prosím znovu.',
|
||||
|
@ -128,9 +128,8 @@ $translations = array(
|
|||
'Create trigger' => 'Vytvořit trigger',
|
||||
'Time' => 'Čas',
|
||||
'Event' => 'Událost',
|
||||
'MySQL version: %s through PHP extension %s' => 'Verze MySQL: %s přes PHP extenzi %s',
|
||||
'%s version: %s through PHP extension %s' => 'Verze %s: %s přes PHP extenzi %s',
|
||||
'%d row(s)' => array('%d řádek', '%d řádky', '%d řádků'),
|
||||
'~ %s' => '~ %s',
|
||||
'Remove' => 'Odebrat',
|
||||
'Are you sure?' => 'Opravdu?',
|
||||
'Privileges' => 'Oprávnění',
|
||||
|
@ -203,7 +202,7 @@ $translations = array(
|
|||
'Select data' => 'Vypsat data',
|
||||
'Stop on error' => 'Zastavit při chybě',
|
||||
'Maximum number of allowed fields exceeded. Please increase %s and %s.' => 'Byl překročen maximální povolený počet polí. Zvyšte prosím %s a %s.',
|
||||
'(anywhere)' => '(kdekoliv)',
|
||||
'anywhere' => 'kdekoliv',
|
||||
'%.3f s' => '%.3f s',
|
||||
'$1-$3-$5' => '$6.$4.$1',
|
||||
'[yyyy]-mm-dd' => 'd.m.[rrrr]',
|
||||
|
@ -229,4 +228,9 @@ $translations = array(
|
|||
'File does not exist.' => 'Soubor neexistuje.',
|
||||
'Permanent login' => 'Trvalé přihlášení',
|
||||
'%d in total' => '%d celkem',
|
||||
'Attachments' => 'Přílohy',
|
||||
'System' => 'Systém',
|
||||
'last' => 'poslední',
|
||||
'Network' => 'Síť',
|
||||
'Geometry' => 'Geometrie',
|
||||
);
|
||||
|
|
|
@ -81,7 +81,7 @@ $translations = array(
|
|||
'File uploads are disabled.' => 'Importieren von Dateien abgeschaltet.',
|
||||
'Routine has been called, %d row(s) affected.' => array('Kommando SQL ausgeführt, %d Datensatz betroffen.', 'Kommando SQL ausgeführt, %d Datensätze betroffen.'),
|
||||
'Call' => 'Aufrufen',
|
||||
'No MySQL extension' => 'Keine MySQL-Erweiterungen installiert',
|
||||
'No extension' => 'Keine Erweiterungen installiert',
|
||||
'None of the supported PHP extensions (%s) are available.' => 'Keine der unterstützten PHP-Erweiterungen (%s) ist vorhanden.',
|
||||
'Session support must be enabled.' => 'Sitzungen müssen aktiviert sein.',
|
||||
'Session expired, please login again.' => 'Sitzungsdauer abgelaufen, bitte erneut anmelden.',
|
||||
|
@ -128,9 +128,8 @@ $translations = array(
|
|||
'Create trigger' => 'Trigger hinzufügen',
|
||||
'Time' => 'Zeitpunkt',
|
||||
'Event' => 'Ereignis',
|
||||
'MySQL version: %s through PHP extension %s' => 'Version MySQL: %s, mit PHP-Erweiterung %s',
|
||||
'%s version: %s through PHP extension %s' => 'Version %s: %s, mit PHP-Erweiterung %s',
|
||||
'%d row(s)' => array('%d Datensatz', '%d Datensätze'),
|
||||
'~ %s' => '~ %s',
|
||||
'Remove' => 'Entfernen',
|
||||
'Are you sure?' => 'Sind Sie sicher ?',
|
||||
'Privileges' => 'Rechte',
|
||||
|
@ -198,12 +197,10 @@ $translations = array(
|
|||
'Partition name' => 'Name der Partition',
|
||||
'Values' => 'Werte',
|
||||
'%d row(s) have been imported.' => array('%d Datensatz importiert.', '%d Datensätze wurden importiert.'),
|
||||
'Show structure' => 'Tabellenstruktur',
|
||||
'(anywhere)' => '(beliebig)',
|
||||
'anywhere' => 'beliebig',
|
||||
'CSV Import' => 'Importiere CSV',
|
||||
'Import' => 'Importieren',
|
||||
'Stop on error' => 'Bei Fehler anhaltan',
|
||||
'Select data' => 'Tabelle auswählen',
|
||||
'%.3f s' => '%.3f s',
|
||||
'$1-$3-$5' => '$6.$4.$1',
|
||||
'[yyyy]-mm-dd' => 't.m.[jjjj]',
|
||||
|
|
|
@ -81,7 +81,7 @@ $translations = array(
|
|||
'File uploads are disabled.' => 'Importación de archivos deshablilitado.',
|
||||
'Routine has been called, %d row(s) affected.' => array('Consulta ejecutada, %d registro afectado.', 'Consulta ejecutada, %d registros afectados.'),
|
||||
'Call' => 'Llamar',
|
||||
'No MySQL extension' => 'No hay extension MySQL',
|
||||
'No extension' => 'No hay extension',
|
||||
'None of the supported PHP extensions (%s) are available.' => 'Ninguna de las extensiones PHP soportadas (%s) está disponible.',
|
||||
'Session support must be enabled.' => 'Deben estar habilitadas las sesiones.',
|
||||
'Session expired, please login again.' => 'Sesión expirada, favor loguéese de nuevo.',
|
||||
|
@ -128,9 +128,8 @@ $translations = array(
|
|||
'Create trigger' => 'Agregar Trigger',
|
||||
'Time' => 'Tiempo',
|
||||
'Event' => 'Evento',
|
||||
'MySQL version: %s through PHP extension %s' => 'Versión MySQL: %s a través de extensión PHP %s',
|
||||
'%s version: %s through PHP extension %s' => 'Versión %s: %s a través de extensión PHP %s',
|
||||
'%d row(s)' => array('%d registro', '%d registros'),
|
||||
'~ %s' => '~ %s',
|
||||
'Remove' => 'Eliminar',
|
||||
'Are you sure?' => 'Está seguro?',
|
||||
'Privileges' => 'Privilegios',
|
||||
|
@ -198,12 +197,10 @@ $translations = array(
|
|||
'Partition name' => 'Nombre de Partición',
|
||||
'Values' => 'Valores',
|
||||
'%d row(s) have been imported.' => array('%d registro importado.', '%d registros importados.'),
|
||||
'Show structure' => 'Información de la Tabla',
|
||||
'(anywhere)' => '(donde sea)',
|
||||
'anywhere' => 'donde sea',
|
||||
'CSV Import' => 'Importar CSV',
|
||||
'Import' => 'Importar',
|
||||
'Stop on error' => 'Parar en caso de error',
|
||||
'Select data' => 'Mostrar datos',
|
||||
'%.3f s' => '%.3f s',
|
||||
'$1-$3-$5' => '$5/$3/$1',
|
||||
'[yyyy]-mm-dd' => 'dd/mm/[aaaa]',
|
||||
|
|
|
@ -81,7 +81,7 @@ $translations = array(
|
|||
'File uploads are disabled.' => 'Failide üleslaadimine on keelatud.',
|
||||
'Routine has been called, %d row(s) affected.' => array('Protseduur täideti edukalt, mõjutatud ridu: %d.', 'Protseduur täideti edukalt, mõjutatud ridu: %d.'),
|
||||
'Call' => 'Käivita',
|
||||
'No MySQL extension' => 'Ei leitud MySQL laiendust',
|
||||
'No extension' => 'Ei leitud laiendust',
|
||||
'None of the supported PHP extensions (%s) are available.' => 'Serveris pole ühtegi toetatud PHP laiendustest (%s).',
|
||||
'Session support must be enabled.' => 'Sessioonid peavad olema lubatud.',
|
||||
'Session expired, please login again.' => 'Sessioon on aegunud, palun logige uuesti sisse.',
|
||||
|
@ -129,7 +129,6 @@ $translations = array(
|
|||
'Time' => 'Aeg',
|
||||
'Event' => 'Sündmus',
|
||||
'%d row(s)' => array('%d rida', '%d rida'),
|
||||
'~ %s' => '~ %s',
|
||||
'Remove' => 'Eemalda',
|
||||
'Are you sure?' => 'Kas oled kindel?',
|
||||
'Privileges' => 'Õigused',
|
||||
|
@ -142,7 +141,7 @@ $translations = array(
|
|||
'Routine' => 'Protseduur',
|
||||
'Grant' => 'Anna',
|
||||
'Revoke' => 'Eemalda',
|
||||
'MySQL version: %s through PHP extension %s' => 'MySQL versioon: %s, kasutatud PHP moodul: %s',
|
||||
'%s version: %s through PHP extension %s' => '%s versioon: %s, kasutatud PHP moodul: %s',
|
||||
'Logged as: %s' => 'Sisse logitud: %s',
|
||||
'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'POST-andmete maht on liialt suur. Palun vähendage andmeid või suurendage %s php-seadet.',
|
||||
'Move up' => 'Liiguta ülespoole',
|
||||
|
@ -198,12 +197,10 @@ $translations = array(
|
|||
'Partition name' => 'Partitsiooni nimi',
|
||||
'Values' => 'Väärtused',
|
||||
'%d row(s) have been imported.' => array('Imporditi %d rida.', 'Imporditi %d rida.'),
|
||||
'Show structure' => 'Tabeli struktuur',
|
||||
'(anywhere)' => '(vahet pole)',
|
||||
'anywhere' => 'vahet pole',
|
||||
'CSV Import' => 'Impordi CSV',
|
||||
'Import' => 'Impordi',
|
||||
'Stop on error' => 'Peatuda vea esinemisel',
|
||||
'Select data' => 'Vali tabel',
|
||||
'%.3f s' => '%.3f s',
|
||||
'$1-$3-$5' => '$6.$4.$1',
|
||||
'[yyyy]-mm-dd' => 'd.m.[yyyy]',
|
||||
|
|
|
@ -81,7 +81,7 @@ $translations = array(
|
|||
'File uploads are disabled.' => 'Importation de fichier désactivé.',
|
||||
'Routine has been called, %d row(s) affected.' => array('Routine exécutée, %d ligne modifiée.', 'Routine exécutée, %d lignes modifiées.'),
|
||||
'Call' => 'Appeler',
|
||||
'No MySQL extension' => 'Extension MySQL introuvable',
|
||||
'No extension' => 'Extension introuvable',
|
||||
'None of the supported PHP extensions (%s) are available.' => 'Aucune des extensions PHP supportées (%s) n\'est disponible.',
|
||||
'Session support must be enabled.' => 'Veuillez activer les sessions.',
|
||||
'Session expired, please login again.' => 'Session expirée, veuillez vous authentifier à nouveau.',
|
||||
|
@ -129,7 +129,6 @@ $translations = array(
|
|||
'Time' => 'Temps',
|
||||
'Event' => 'Évènement',
|
||||
'%d row(s)' => array('%d ligne', '%d lignes'),
|
||||
'~ %s' => '~ %s',
|
||||
'Remove' => 'Effacer',
|
||||
'Are you sure?' => 'Êtes-vous certain?',
|
||||
'Privileges' => 'Privilège',
|
||||
|
@ -142,7 +141,7 @@ $translations = array(
|
|||
'Routine' => 'Routine',
|
||||
'Grant' => 'Grant',
|
||||
'Revoke' => 'Revoke',
|
||||
'MySQL version: %s through PHP extension %s' => 'Version de MySQL: %s utilisant l\'extension %s',
|
||||
'%s version: %s through PHP extension %s' => 'Version de %s: %s utilisant l\'extension %s',
|
||||
'Logged as: %s' => 'Authentifié en tant que %s',
|
||||
'Too big POST data. Reduce the data or increase the %s configuration directive.' => 'Donnée POST trop grande . Réduire la taille des données ou modifier le %s dans la configuration de PHP.',
|
||||
'Move up' => 'Déplacer vers le haut',
|
||||
|
@ -198,12 +197,10 @@ $translations = array(
|
|||
'Partition name' => 'Nom de la partition',
|
||||
'Values' => 'Valeurs',
|
||||
'%d row(s) have been imported.' => array('%d ligne a été importé.','%d lignes ont été importé.'),
|
||||
'Show structure' => 'Structure de la table',
|
||||
'(anywhere)' => '(n\'importe où)',
|
||||
'anywhere' => 'n\'importe où',
|
||||
'CSV Import' => 'Importation CVS',
|
||||
'Import' => 'Importer',
|
||||
'Stop on error' => 'Arrêt sur erreur',
|
||||
'Select data' => 'Selectionner la table',
|
||||
'%.3f s' => '%.3f s',
|
||||
'$1-$3-$5' => '$5/$3/$1',
|
||||
'[yyyy]-mm-dd' => 'jj/mm/[aaaa]',
|
||||
|
|
|
@ -81,7 +81,7 @@ $translations = array(
|
|||
'File uploads are disabled.' => 'Caricamento file disabilitato.',
|
||||
'Routine has been called, %d row(s) affected.' => array('Routine chiamata, %d riga interessata.', 'Routine chiamata, %d righe interessate.'),
|
||||
'Call' => 'Chiama',
|
||||
'No MySQL extension' => 'Estensioni MySQL non presenti',
|
||||
'No extension' => 'Estensioni non presenti',
|
||||
'None of the supported PHP extensions (%s) are available.' => 'Nessuna delle estensioni PHP supportate (%s) disponibile.',
|
||||
'Session support must be enabled.' => 'Le sessioni devono essere abilitate.',
|
||||
'Session expired, please login again.' => 'Sessione scaduta, autenticarsi di nuovo.',
|
||||
|
@ -128,9 +128,8 @@ $translations = array(
|
|||
'Create trigger' => 'Crea trigger',
|
||||
'Time' => 'Orario',
|
||||
'Event' => 'Evento',
|
||||
'MySQL version: %s through PHP extension %s' => 'Versione MySQL: %s via estensione PHP %s',
|
||||
'%s version: %s through PHP extension %s' => 'Versione %s: %s via estensione PHP %s',
|
||||
'%d row(s)' => array('%d riga', '%d righe'),
|
||||
'~ %s' => '~ %s',
|
||||
'Remove' => 'Rimuovi',
|
||||
'Are you sure?' => 'Sicuro?',
|
||||
'Privileges' => 'Privilegi',
|
||||
|
@ -198,12 +197,10 @@ $translations = array(
|
|||
'Partition name' => 'Nome partizione',
|
||||
'Values' => 'Valori',
|
||||
'%d row(s) have been imported.' => array('%d riga importata.','%d righe importate.'),
|
||||
'Show structure' => 'Struttura tabella',
|
||||
'(anywhere)' => '(ovunque)',
|
||||
'anywhere' => 'ovunque',
|
||||
'CSV Import' => 'Importa da CSV',
|
||||
'Import' => 'Importa',
|
||||
'Stop on error' => 'Stop su errore',
|
||||
'Select data' => 'Scegli tabella',
|
||||
'%.3f s' => '%.3f s',
|
||||
'$1-$3-$5' => '$5/$3/$1',
|
||||
'[yyyy]-mm-dd' => 'dd/mm/[yyyy]',
|
||||
|
|
|
@ -81,7 +81,7 @@ $translations = array(
|
|||
'File uploads are disabled.' => 'Bestanden uploaden is uitgeschakeld.',
|
||||
'Routine has been called, %d row(s) affected.' => array('Procedure uitgevoerd, %d rij geraakt.', 'Procedure uitgevoerd, %d rijen geraakt.'),
|
||||
'Call' => 'Uitvoeren',
|
||||
'No MySQL extension' => 'Geen MySQL extensie',
|
||||
'No extension' => 'Geen extensie',
|
||||
'None of the supported PHP extensions (%s) are available.' => 'Geen geldige PHP extensies beschikbaar (%s).',
|
||||
'Session support must be enabled.' => 'Sessies moeten geactiveerd zijn.',
|
||||
'Session expired, please login again.' => 'Uw sessie is verlopen. Gelieve opnieuw in te loggen.',
|
||||
|
@ -128,9 +128,8 @@ $translations = array(
|
|||
'Create trigger' => 'Trigger aanmaken',
|
||||
'Time' => 'Time',
|
||||
'Event' => 'Event',
|
||||
'MySQL version: %s through PHP extension %s' => 'MySQL versie: %s met PHP extensie %s',
|
||||
'%s version: %s through PHP extension %s' => '%s versie: %s met PHP extensie %s',
|
||||
'%d row(s)' => array('%d rij', '%d rijen'),
|
||||
'~ %s' => '~ %s',
|
||||
'Remove' => 'Verwijderen',
|
||||
'Are you sure?' => 'Weet u het zeker?',
|
||||
'Privileges' => 'Rechten',
|
||||
|
@ -198,12 +197,10 @@ $translations = array(
|
|||
'Partition name' => 'Partitie naam',
|
||||
'Values' => 'Waarden',
|
||||
'%d row(s) have been imported.' => array('%d rij werd geïmporteerd.', '%d rijen werden geïmporteerd.'),
|
||||
'Show structure' => 'Tabelstructuur',
|
||||
'(anywhere)' => '(overal)',
|
||||
'anywhere' => 'overal',
|
||||
'CSV Import' => 'CSV Import',
|
||||
'Import' => 'Importeren',
|
||||
'Stop on error' => 'Stoppen bij fout',
|
||||
'Select data' => 'Selecteer tabel',
|
||||
'%.3f s' => '%.3f s',
|
||||
'$1-$3-$5' => '$5-$3-$1',
|
||||
'[yyyy]-mm-dd' => 'dd-mm-[jjjj]',
|
||||
|
|
|
@ -81,7 +81,7 @@ $translations = array(
|
|||
'File uploads are disabled.' => 'Загрузка файлов на сервер запрещена.',
|
||||
'Routine has been called, %d row(s) affected.' => array('Была вызвана процедура, %d запись была изменена.', 'Была вызвана процедура, %d записи было изменено.', 'Была вызвана процедура, %d записей было изменено.'),
|
||||
'Call' => 'Вызвать',
|
||||
'No MySQL extension' => 'Нет MySQL расширений',
|
||||
'No extension' => 'Нет расширений',
|
||||
'None of the supported PHP extensions (%s) are available.' => 'Не доступно ни одного расширения из поддерживаемых (%s).',
|
||||
'Session support must be enabled.' => 'Сессии должны быть включены.',
|
||||
'Session expired, please login again.' => 'Срок действия сесси истек, нужно снова войти в систему.',
|
||||
|
@ -128,9 +128,8 @@ $translations = array(
|
|||
'Create trigger' => 'Создать триггер',
|
||||
'Time' => 'Время',
|
||||
'Event' => 'Событие',
|
||||
'MySQL version: %s through PHP extension %s' => 'Версия MySQL: %s с PHP-расширением %s',
|
||||
'%s version: %s through PHP extension %s' => 'Версия %s: %s с PHP-расширением %s',
|
||||
'%d row(s)' => array('%d строка', '%d строки', '%d строк'),
|
||||
'~ %s' => '~ %s',
|
||||
'Remove' => 'Удалить',
|
||||
'Are you sure?' => 'Вы уверены?',
|
||||
'Privileges' => 'Полномочия',
|
||||
|
@ -199,11 +198,9 @@ $translations = array(
|
|||
'%d row(s) have been imported.' => array('Импортирована %d строка.', 'Импортировано %d строки.', 'Импортировано %d строк.'),
|
||||
'CSV Import' => 'Импорт CSV',
|
||||
'Import' => 'Импорт',
|
||||
'Show structure' => 'Структура таблицы',
|
||||
'Select data' => 'Выбрать данные из таблицы',
|
||||
'Stop on error' => 'Остановить при ошибке',
|
||||
'Maximum number of allowed fields exceeded. Please increase %s and %s.' => 'Достигнуто максимальное значение количества доступных полей. Увеличьте %s и %s.',
|
||||
'(anywhere)' => '(в любом месте)',
|
||||
'anywhere' => 'в любом месте',
|
||||
'%.3f s' => '%.3f s',
|
||||
'$1-$3-$5' => '$5.$3.$1',
|
||||
'[yyyy]-mm-dd' => 'дд.мм.[гггг]',
|
||||
|
|
|
@ -81,7 +81,7 @@ $translations = array(
|
|||
'File uploads are disabled.' => 'Nahrávánie súborov nie je povolené.',
|
||||
'Routine has been called, %d row(s) affected.' => array('Procedúra bola zavolaná, bol zmenený %d záznam.', 'Procedúra bola zavolaná, boli zmenené %d záznamy.', 'Procedúra bola zavolaná, bolo zmenených %d záznamov.'),
|
||||
'Call' => 'Zavolať',
|
||||
'No MySQL extension' => 'Žiadne MySQL rozšírenie',
|
||||
'No extension' => 'Žiadne rozšírenie',
|
||||
'None of the supported PHP extensions (%s) are available.' => 'Nie je dostupné žiadne z podporovaných rozšírení (%s).',
|
||||
'Session support must be enabled.' => 'Session premenné musia byť povolené.',
|
||||
'Session expired, please login again.' => 'Session vypršala, prihláste sa prosím znova.',
|
||||
|
@ -128,9 +128,8 @@ $translations = array(
|
|||
'Create trigger' => 'Vytvoriť trigger',
|
||||
'Time' => 'Čas',
|
||||
'Event' => 'Udalosť',
|
||||
'MySQL version: %s through PHP extension %s' => 'Verzia MySQL: %s cez PHP rozšírenie %s',
|
||||
'%s version: %s through PHP extension %s' => 'Verzia %s: %s cez PHP rozšírenie %s',
|
||||
'%d row(s)' => array('%d riadok', '%d riadky', '%d riadkov'),
|
||||
'~ %s' => '~ %s',
|
||||
'Remove' => 'Odobrať',
|
||||
'Are you sure?' => 'Naozaj?',
|
||||
'Privileges' => 'Oprávnenia',
|
||||
|
@ -199,11 +198,9 @@ $translations = array(
|
|||
'%d row(s) have been imported.' => array('Bol importovaný %d záznam.', 'Boli importované %d záznamy.', 'Bolo importovaných %d záznamov.'),
|
||||
'CSV Import' => 'Import CSV',
|
||||
'Import' => 'Import',
|
||||
'Show structure' => 'Štruktúra tabuľky',
|
||||
'Select data' => 'Vypísať tabuľku',
|
||||
'Stop on error' => 'Zastaviť pri chybe',
|
||||
'Maximum number of allowed fields exceeded. Please increase %s and %s.' => 'Bol prekročený maximálny počet povolených polí. Zvýšte prosím %s a %s.',
|
||||
'(anywhere)' => '(kdekoľvek)',
|
||||
'anywhere' => 'kdekoľvek',
|
||||
'%.3f s' => '%.3f s',
|
||||
'$1-$3-$5' => '$6.$4.$1',
|
||||
'[yyyy]-mm-dd' => 'd.m.[rrrr]',
|
||||
|
|
|
@ -79,7 +79,7 @@ $translations = array(
|
|||
'File uploads are disabled.' => '檔案上傳被禁用。',
|
||||
'Routine has been called, %d row(s) affected.' => '程序已被執行,%d行被影響',
|
||||
'Call' => '呼叫',
|
||||
'No MySQL extension' => '沒有 MySQL 擴充模組',
|
||||
'No extension' => '沒有 擴充模組',
|
||||
'None of the supported PHP extensions (%s) are available.' => '沒有任何支援的PHP擴充模組(%s)。',
|
||||
'Session support must be enabled.' => 'Session 必須被啟用。',
|
||||
'Session expired, please login again.' => 'Session 已過期,請重新登入。',
|
||||
|
@ -126,9 +126,8 @@ $translations = array(
|
|||
'Create trigger' => '建立觸發器',
|
||||
'Time' => '時間',
|
||||
'Event' => '事件',
|
||||
'MySQL version: %s through PHP extension %s' => 'MySQL版本:%s 透過PHP擴充模組 %s',
|
||||
'%s version: %s through PHP extension %s' => '%s版本:%s 透過PHP擴充模組 %s',
|
||||
'%d row(s)' => '%d行',
|
||||
'~ %s' => '~ %s',
|
||||
'Remove' => '移除',
|
||||
'Are you sure?' => '你確定嗎?',
|
||||
'Privileges' => '權限',
|
||||
|
@ -196,12 +195,10 @@ $translations = array(
|
|||
'Partition name' => '分區名',
|
||||
'Values' => '值',
|
||||
'%d row(s) have been imported.' => '%d行已導入。',
|
||||
'Show structure' => '資料表結構',
|
||||
'(anywhere)' => '(任意位置)',
|
||||
'anywhere' => '任意位置',
|
||||
'CSV Import' => '匯入 CSV',
|
||||
'Import' => '匯入',
|
||||
'Stop on error' => '出錯時停止',
|
||||
'Select data' => '選擇資料表',
|
||||
'%.3f s' => '%.3f秒',
|
||||
'$1-$3-$5' => '$1.$3.$5',
|
||||
'[yyyy]-mm-dd' => '[yyyy].mm.dd',
|
||||
|
|
|
@ -81,7 +81,7 @@ $translations = array(
|
|||
'File uploads are disabled.' => '文件上传被禁用。',
|
||||
'Routine has been called, %d row(s) affected.' => '子程序被调用,%d 行被影响',
|
||||
'Call' => '调用',
|
||||
'No MySQL extension' => '没有MySQL扩展',
|
||||
'No extension' => '没有扩展',
|
||||
'None of the supported PHP extensions (%s) are available.' => '没有支持的 PHP 扩展可用(%s)。',
|
||||
'Session support must be enabled.' => '会话必须被启用。',
|
||||
'Session expired, please login again.' => '会话已过期,请重新登录。',
|
||||
|
@ -128,9 +128,8 @@ $translations = array(
|
|||
'Create trigger' => '创建触发器',
|
||||
'Time' => '时间',
|
||||
'Event' => '事件',
|
||||
'MySQL version: %s through PHP extension %s' => 'MySQL 版本:%s 通过 PHP 扩展 %s',
|
||||
'%s version: %s through PHP extension %s' => '%s 版本:%s 通过 PHP 扩展 %s',
|
||||
'%d row(s)' => '%d 行',
|
||||
'~ %s' => '~ %s',
|
||||
'Remove' => '移除',
|
||||
'Are you sure?' => '你确定吗?',
|
||||
'Privileges' => '权限',
|
||||
|
@ -198,12 +197,10 @@ $translations = array(
|
|||
'Partition name' => '分区名',
|
||||
'Values' => '值',
|
||||
'%d row(s) have been imported.' => '%d 行已导入。',
|
||||
'Show structure' => '表结构',
|
||||
'(anywhere)' => '(任意位置)',
|
||||
'anywhere' => '任意位置',
|
||||
'CSV Import' => 'CSV 导入',
|
||||
'Import' => '导入',
|
||||
'Stop on error' => '出错时停止',
|
||||
'Select data' => '选择表',
|
||||
'%.3f s' => '%.3f 秒',
|
||||
'$1-$3-$5' => '$1.$3.$5',
|
||||
'[yyyy]-mm-dd' => '[yyyy].mm.dd',
|
||||
|
|
|
@ -5,8 +5,7 @@ $result = $connection->query("SELECT User, Host FROM mysql.user ORDER BY Host, U
|
|||
if (!$result) {
|
||||
?>
|
||||
<form action=""><p>
|
||||
<?php echo SID_FORM; ?>
|
||||
<?php if ($_GET["server"] != "") { ?><input type="hidden" name="server" value="<?php echo h($_GET["server"]); ?>"><?php } ?>
|
||||
<?php hidden_fields_get(); ?>
|
||||
<?php echo lang('Username'); ?>: <input name="user">
|
||||
<?php echo lang('Server'); ?>: <input name="host" value="localhost">
|
||||
<input type="hidden" name="grant" value="">
|
||||
|
|
|
@ -7,7 +7,7 @@ $table_pos_js = array();
|
|||
preg_match_all('~([^:]+):([-0-9.]+)x([-0-9.]+)(_|$)~', $_COOKIE["adminer_schema"], $matches, PREG_SET_ORDER); //! ':' in table name
|
||||
foreach ($matches as $i => $match) {
|
||||
$table_pos[$match[1]] = array($match[2], $match[3]);
|
||||
$table_pos_js[] = "\n\t'" . addcslashes($match[1], "\r\n'\\") . "': [ $match[2], $match[3] ]";
|
||||
$table_pos_js[] = "\n\t'" . addcslashes($match[1], "\r\n'\\/") . "': [ $match[2], $match[3] ]";
|
||||
}
|
||||
|
||||
$top = 0;
|
||||
|
@ -27,7 +27,7 @@ foreach (table_status() as $row) {
|
|||
$schema[$row["Name"]]["fields"][$name] = $field;
|
||||
}
|
||||
$schema[$row["Name"]]["pos"] = ($table_pos[$row["Name"]] ? $table_pos[$row["Name"]] : array($top, 0));
|
||||
if ($row["Engine"] == "InnoDB") {
|
||||
if (fk_support($row)) {
|
||||
foreach (foreign_keys($row["Name"]) as $val) {
|
||||
if (!$val["db"]) {
|
||||
$left = $base_left;
|
||||
|
|
|
@ -26,6 +26,12 @@ $limit = $adminer->selectLimitProcess();
|
|||
$from = ($select ? implode(", ", $select) : "*") . "\nFROM " . idf_escape($TABLE) . ($where ? "\nWHERE " . implode(" AND ", $where) : "");
|
||||
$group_by = ($group && count($group) < count($select) ? "\nGROUP BY " . implode(", ", $group) : "") . ($order ? "\nORDER BY " . implode(", ", $order) : "");
|
||||
|
||||
if ($_GET["page"] == "last") {
|
||||
session_write_close();
|
||||
$found_rows = $connection->result("SELECT COUNT(*) FROM " . idf_escape($TABLE) . ($where ? " WHERE " . implode(" AND ", $where) : ""));
|
||||
redirect(remove_from_uri("page") . ($found_rows > $limit ? "&page=" . floor(($found_rows - 1) / $limit) : ""));
|
||||
}
|
||||
|
||||
if ($_POST && !$error) {
|
||||
$where_check = "(" . implode(") OR (", array_map('where_check', (array) $_POST["check"])) . ")";
|
||||
$primary = ($indexes["PRIMARY"] ? ($select ? array_flip($indexes["PRIMARY"]["columns"]) : array()) : null); // empty array means that all primary fields are selected
|
||||
|
@ -43,7 +49,7 @@ if ($_POST && !$error) {
|
|||
if ($select) {
|
||||
$row = array();
|
||||
foreach ($select as $val) {
|
||||
$row[] = (ereg('^`(.*)`$', $val, $match) ? idf_unescape($match[1]) : $val); //! columns looking like functions
|
||||
$row[] = (ereg('^`.*`$', $val) ? idf_unescape($val) : $val); //! columns looking like functions
|
||||
}
|
||||
}
|
||||
dump_csv($row);
|
||||
|
@ -54,7 +60,7 @@ if ($_POST && !$error) {
|
|||
$union = array();
|
||||
foreach ($_POST["check"] as $val) {
|
||||
// where is not unique so OR can't be used
|
||||
$union[] = "(SELECT $from " . ($where ? "AND " : "WHERE ") . where_check($val) . $group_by . " LIMIT 1)";
|
||||
$union[] = "(SELECT" . limit("$from " . ($where ? "AND " : "WHERE ") . where_check($val) . $group_by, 1) . ")";
|
||||
}
|
||||
dump_data($TABLE, "INSERT", implode(" UNION ALL ", $union));
|
||||
}
|
||||
|
@ -64,27 +70,38 @@ if ($_POST && !$error) {
|
|||
if (!$_POST["import"]) { // edit
|
||||
$result = true;
|
||||
$affected = 0;
|
||||
$command = ($_POST["delete"] ? "DELETE FROM " : ($_POST["clone"] ? "INSERT INTO " : "UPDATE ")) . idf_escape($TABLE);
|
||||
$query = idf_escape($TABLE);
|
||||
$set = array();
|
||||
if (!$_POST["delete"]) {
|
||||
foreach ($columns as $name => $val) { //! should check also for edit or insert privileges
|
||||
$val = process_input($fields[$name]);
|
||||
if ($_POST["clone"]) {
|
||||
$set[idf_escape($name)] = ($val !== false ? $val : idf_escape($name));
|
||||
} elseif ($val !== false) {
|
||||
$set[] = idf_escape($name) . " = $val";
|
||||
if ($val !== null) {
|
||||
if ($_POST["clone"]) {
|
||||
$set[idf_escape($name)] = ($val !== false ? $val : idf_escape($name));
|
||||
} elseif ($val !== false) {
|
||||
$set[] = idf_escape($name) . " = $val";
|
||||
}
|
||||
}
|
||||
}
|
||||
$command .= ($_POST["clone"] ? " (" . implode(", ", array_keys($set)) . ")\nSELECT " . implode(", ", $set) . "\nFROM " . idf_escape($TABLE) : " SET\n" . implode(",\n", $set));
|
||||
$query .= ($_POST["clone"] ? " (" . implode(", ", array_keys($set)) . ")\nSELECT " . implode(", ", $set) . "\nFROM " . idf_escape($TABLE) : " SET\n" . implode(",\n", $set));
|
||||
}
|
||||
if ($_POST["delete"] || $set) {
|
||||
if ($_POST["all"] || ($primary === array() && $_POST["check"])) {
|
||||
$result = queries($command . ($_POST["all"] ? ($where ? "\nWHERE " . implode(" AND ", $where) : "") : "\nWHERE $where_check"));
|
||||
$command = "UPDATE";
|
||||
if ($_POST["delete"]) {
|
||||
$command = "DELETE";
|
||||
$query = "FROM $query";
|
||||
}
|
||||
if ($_POST["clone"]) {
|
||||
$command = "INSERT";
|
||||
$query = "INTO $query";
|
||||
}
|
||||
if ($_POST["all"] || ($primary === array() && $_POST["check"]) || count($group) < count($select)) {
|
||||
$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) {
|
||||
// where is not unique so OR can't be used
|
||||
$result = queries($command . "\nWHERE " . where_check($val) . (count($group) < count($select) ? "" : "\nLIMIT 1"));
|
||||
$result = queries($command . limit1($query . "\nWHERE " . where_check($val)));
|
||||
if (!$result) {
|
||||
break;
|
||||
}
|
||||
|
@ -101,8 +118,9 @@ if ($_POST && !$error) {
|
|||
preg_match_all('~(?>"[^"]*"|[^"\\r\\n]+)+~', $file, $matches);
|
||||
$affected = count($matches[0]);
|
||||
queries("START TRANSACTION");
|
||||
$separator = ($_POST["separator"] == ";" ? ";" : ",");
|
||||
foreach ($matches[0] as $key => $val) {
|
||||
preg_match_all('~(("[^"]*")+|[^,]*),~', "$val,", $matches2);
|
||||
preg_match_all("~((\"[^\"]*\")+|[^$separator]*)$separator~", $val . $separator, $matches2);
|
||||
if (!$key && !array_diff($matches2[1], $cols)) { //! doesn't work with column names containing ",\n
|
||||
// first row corresponds to column names - use it for table structure
|
||||
$cols = $matches2[1];
|
||||
|
@ -120,7 +138,7 @@ if ($_POST && !$error) {
|
|||
}
|
||||
}
|
||||
if ($result) {
|
||||
queries("COMMIT");
|
||||
queries("COMMIT");
|
||||
}
|
||||
queries_redirect(remove_from_uri("page"), lang('%d row(s) have been imported.', $affected), $result);
|
||||
queries("ROLLBACK");
|
||||
|
@ -147,11 +165,11 @@ if (isset($rights["insert"])) {
|
|||
$adminer->selectLinks($table_status, $set);
|
||||
|
||||
if (!$columns) {
|
||||
echo "<p class='error'>" . lang('Unable to select the table') . ($fields ? "" : ": " . error()) . ".\n";
|
||||
echo "<p class='error'>" . lang('Unable to select the table') . ($fields ? "." : ": " . error()) . "\n";
|
||||
} else {
|
||||
echo "<form action='' id='form'>\n";
|
||||
echo "<div style='display: none;'>";
|
||||
echo ($_GET["server"] != "" ? '<input type="hidden" name="server" value="' . h($_GET["server"]) . '">' : "");
|
||||
hidden_fields_get();
|
||||
echo (DB != "" ? '<input type="hidden" name="db" value="' . h(DB) . '">' : ""); // not used in Editor
|
||||
echo '<input type="hidden" name="select" value="' . h($TABLE) . '">';
|
||||
echo "</div>\n";
|
||||
|
@ -163,7 +181,7 @@ if (!$columns) {
|
|||
$adminer->selectActionPrint($text_length);
|
||||
echo "</form>\n";
|
||||
|
||||
$query = "SELECT " . (intval($limit) && $group && count($group) < count($select) ? "SQL_CALC_FOUND_ROWS " : "") . $from . $group_by . ($limit != "" ? "\nLIMIT " . intval($limit) . ($_GET["page"] ? " OFFSET " . ($limit * $_GET["page"]) : "") : "");
|
||||
$query = "SELECT" . limit((intval($limit) && $group && count($group) < count($select) && $driver == "sql" ? "SQL_CALC_FOUND_ROWS " : "") . $from . $group_by, ($limit != "" ? intval($limit) : null), ($_GET["page"] ? $limit * $_GET["page"] : 0));
|
||||
echo $adminer->selectQuery($query);
|
||||
|
||||
$result = $connection->query($query);
|
||||
|
@ -172,19 +190,19 @@ if (!$columns) {
|
|||
} else {
|
||||
$email_fields = array();
|
||||
echo "<form action='' method='post' enctype='multipart/form-data'>\n";
|
||||
if (!$result->num_rows) {
|
||||
$rows = array();
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$rows[] = $row;
|
||||
}
|
||||
// use count($rows) without LIMIT, COUNT(*) without grouping, FOUND_ROWS otherwise (slowest)
|
||||
$found_rows = (intval($limit) && $group && count($group) < count($select)
|
||||
? ($driver == "sql" ? $connection->result(" SELECT FOUND_ROWS()") : $connection->result("SELECT COUNT(*) FROM ($query) x")) // space to allow mysql.trace_mode
|
||||
: count($rows)
|
||||
);
|
||||
|
||||
if (!$rows) {
|
||||
echo "<p class='message'>" . lang('No rows.') . "\n";
|
||||
} else {
|
||||
$rows = array();
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$rows[] = $row;
|
||||
}
|
||||
// use count($rows) without LIMIT, COUNT(*) without grouping, FOUND_ROWS otherwise (slowest)
|
||||
$found_rows = (intval($limit) && $group && count($group) < count($select)
|
||||
? $connection->result($connection->query(" SELECT FOUND_ROWS()")) // space to allow mysql.trace_mode
|
||||
: count($rows)
|
||||
);
|
||||
|
||||
$backward_keys = $adminer->backwardKeys($TABLE, $table_name);
|
||||
|
||||
echo "<table cellspacing='0' class='nowrap' onclick='tableClick(event);'>\n";
|
||||
|
@ -205,7 +223,7 @@ if (!$columns) {
|
|||
}
|
||||
echo ($backward_keys ? "<th>" . lang('Relations') : "") . "</thead>\n";
|
||||
foreach ($adminer->rowDescriptions($rows, $foreign_keys) as $n => $row) {
|
||||
$unique_array = unique_array($row, $indexes);
|
||||
$unique_array = unique_array($rows[$n], $indexes);
|
||||
$unique_idf = "";
|
||||
foreach ($unique_array as $key => $val) {
|
||||
$unique_idf .= "&" . (isset($val) ? urlencode("where[" . bracket_escape($key) . "]") . "=" . urlencode($val) : "null%5B%5D=" . urlencode($key));
|
||||
|
@ -222,7 +240,7 @@ if (!$columns) {
|
|||
if (!isset($val)) {
|
||||
$val = "<i>NULL</i>";
|
||||
} else {
|
||||
if (ereg('blob|binary', $field["type"]) && $val != "") {
|
||||
if (ereg('binary|blob|bytea', $field["type"]) && $val != "") {
|
||||
$link = h(ME . 'download=' . urlencode($TABLE) . '&field=' . urlencode($key) . $unique_idf);
|
||||
}
|
||||
if ($val == "") {
|
||||
|
@ -271,33 +289,45 @@ if (!$columns) {
|
|||
echo "</tr>\n"; // close to allow white-space: pre
|
||||
}
|
||||
echo "</table>\n";
|
||||
|
||||
if (intval($limit) && count($group) >= count($select)) {
|
||||
// slow with big tables
|
||||
ob_flush();
|
||||
flush();
|
||||
$found_rows = $connection->result($connection->query("SELECT COUNT(*) FROM " . idf_escape($TABLE) . ($where ? " WHERE " . implode(" AND ", $where) : "")));
|
||||
}
|
||||
|
||||
parse_str($_COOKIE["adminer_export"], $adminer_export);
|
||||
|
||||
if ($rows || $_GET["page"]) {
|
||||
$exact_count = true;
|
||||
if (intval($limit) && count($group) >= count($select) && ($found_rows >= $limit || $_GET["page"])) {
|
||||
$found_rows = $table_status["Rows"];
|
||||
if (!isset($found_rows) || $where || $_GET["page"] * $limit * 2 > $found_rows || ($table_status["Engine"] == "InnoDB" && $found_rows < 1e5)) {
|
||||
// slow with big tables
|
||||
ob_flush();
|
||||
flush();
|
||||
$found_rows = $connection->result("SELECT COUNT(*) FROM " . idf_escape($TABLE) . ($where ? " WHERE " . implode(" AND ", $where) : ""));
|
||||
} else {
|
||||
$exact_count = false;
|
||||
}
|
||||
}
|
||||
echo "<p class='pages'>";
|
||||
if (intval($limit) && $found_rows > $limit) {
|
||||
// display first, previous 3, next 3 and last page
|
||||
// display first, previous 5, next 5 and last page
|
||||
$max_page = floor(($found_rows - 1) / $limit);
|
||||
echo lang('Page') . ":" . pagination(0) . ($_GET["page"] > 3 ? " ..." : "");
|
||||
for ($i = max(1, $_GET["page"] - 2); $i < min($max_page, $_GET["page"] + 3); $i++) {
|
||||
echo lang('Page') . ":" . pagination(0) . ($_GET["page"] > 5 ? " ..." : "");
|
||||
for ($i = max(1, $_GET["page"] - 2); $i < min($max_page, $_GET["page"] + 5); $i++) {
|
||||
echo pagination($i);
|
||||
}
|
||||
echo ($_GET["page"] + 3 < $max_page ? " ..." : "") . pagination($max_page);
|
||||
echo ($_GET["page"] + 5 < $max_page ? " ..." : "") . ($exact_count ? pagination($max_page) : ' <a href="' . h(remove_from_uri() . "&page=last") . '">' . lang('last') . "</a>");
|
||||
}
|
||||
echo " (" . lang('%d row(s)', $found_rows) . ") " . checkbox("all", 1, 0, lang('whole result')) . "\n";
|
||||
echo " (" . ($exact_count ? "" : "~ ") . lang('%d row(s)', $found_rows) . ") " . checkbox("all", 1, 0, lang('whole result')) . "\n";
|
||||
|
||||
echo (information_schema(DB) ? "" : "<fieldset><legend>" . lang('Edit') . "</legend><div><input type='submit' name='edit' value='" . lang('Edit') . "'> <input type='submit' name='clone' value='" . lang('Clone') . "'> <input type='submit' name='delete' value='" . lang('Delete') . "' onclick=\"return confirm('" . lang('Are you sure?') . " (' + (this.form['all'].checked ? $found_rows : formChecked(this, /check/)) + ')');\"></div></fieldset>\n");
|
||||
print_fieldset("export", lang('Export'));
|
||||
echo $adminer->dumpOutput(1) . " " . $adminer->dumpFormat(1); // 1 - select
|
||||
echo $adminer->dumpOutput(1, $adminer_export["output"]) . " " . $adminer->dumpFormat(1, $adminer_export["format"]); // 1 - select
|
||||
echo " <input type='submit' name='export' value='" . lang('Export') . "'>\n";
|
||||
echo "</div></fieldset>\n";
|
||||
}
|
||||
print_fieldset("import", lang('CSV Import'), !$result->num_rows);
|
||||
echo "<input type='hidden' name='token' value='$token'><input type='file' name='csv_file'> <input type='submit' name='import' value='" . lang('Import') . "'>\n";
|
||||
echo "<input type='hidden' name='token' value='$token'><input type='file' name='csv_file'> ";
|
||||
echo html_select("separator", array(",", ";"), ($adminer_export["format"] == "csv;" ? ";" : ","), 1); // 1 - select
|
||||
echo " <input type='submit' name='import' value='" . lang('Import') . "'>\n";
|
||||
echo "</div></fieldset>\n";
|
||||
|
||||
$adminer->selectEmailPrint(array_filter($email_fields, 'strlen'), $columns);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
restart_session();
|
||||
$history = &$_SESSION["history"][$_GET["server"]][DB];
|
||||
$history_all = &get_session("history");
|
||||
$history = &$history_all[DB];
|
||||
if (!$error && $_POST["clear"]) {
|
||||
$history = array();
|
||||
redirect(remove_from_uri("history"));
|
||||
|
@ -28,15 +29,14 @@ if (!$error && $_POST) {
|
|||
$history[] = $query;
|
||||
}
|
||||
$space = "(\\s|/\\*.*\\*/|(#|-- )[^\n]*\n|--\n)";
|
||||
$alter_database = "(CREATE|DROP)$space+(DATABASE|SCHEMA)\\b~isU";
|
||||
if (!ini_get("session.use_cookies")) {
|
||||
if (!ini_bool("session.use_cookies")) {
|
||||
session_write_close();
|
||||
}
|
||||
$delimiter = ";";
|
||||
$offset = 0;
|
||||
$empty = true;
|
||||
$connection2 = (DB != "" ? connect() : null); // connection for exploring indexes and EXPLAIN (to not replace FOUND_ROWS()) //! PDO - silent error
|
||||
if (is_object($connection2)) {
|
||||
$connection2 = connect(); // connection for exploring indexes and EXPLAIN (to not replace FOUND_ROWS()) //! PDO - silent error
|
||||
if (is_object($connection2) && DB != "") {
|
||||
$connection2->select_db(DB);
|
||||
}
|
||||
$queries = 0;
|
||||
|
@ -59,7 +59,7 @@ if (!$error && $_POST) {
|
|||
$empty = false;
|
||||
$q = substr($query, 0, $match[0][1]);
|
||||
$queries++;
|
||||
echo "<pre class='jush-sql' id='sql-$queries'>" . shorten_utf8(trim($q), 1000) . "</pre>\n";
|
||||
echo "<pre class='jush-$driver' id='sql-$queries'>" . shorten_utf8(trim($q), 1000) . "</pre>\n";
|
||||
ob_flush();
|
||||
flush(); // can take a long time - show the running query
|
||||
$start = explode(" ", microtime()); // microtime(true) is available since PHP 5
|
||||
|
@ -71,6 +71,9 @@ if (!$error && $_POST) {
|
|||
break;
|
||||
}
|
||||
} else {
|
||||
if (is_object($connection2) && preg_match("~^$space*(USE)\\b~isU", $q)) {
|
||||
$connection2->query($q);
|
||||
}
|
||||
do {
|
||||
$result = $connection->store_result();
|
||||
$end = explode(" ", microtime());
|
||||
|
@ -82,18 +85,17 @@ if (!$error && $_POST) {
|
|||
$id = "explain-$queries";
|
||||
echo ", <a href='#$id' onclick=\"return !toggle('$id');\">EXPLAIN</a>\n";
|
||||
echo "<div id='$id' class='hidden'>\n";
|
||||
select($connection2->query("EXPLAIN $q"));
|
||||
select(explain($connection2, $q));
|
||||
echo "</div>\n";
|
||||
}
|
||||
} else {
|
||||
if (preg_match("~^$space*$alter_database", $query)) {
|
||||
if (preg_match("~^$space*(CREATE|DROP|ALTER)$space+(DATABASE|SCHEMA)\\b~isU", $q)) {
|
||||
restart_session();
|
||||
$_SESSION["databases"][$_GET["server"]] = null; // clear cache
|
||||
set_session("databases", null); // clear cache
|
||||
session_write_close();
|
||||
}
|
||||
echo "<p class='message' title='" . h($connection->info) . "'>" . lang('Query executed OK, %d row(s) affected.', $connection->affected_rows) . "$time\n";
|
||||
}
|
||||
unset($result); // free resultset
|
||||
$start = $end;
|
||||
} while ($connection->next_result());
|
||||
}
|
||||
|
@ -119,6 +121,7 @@ if (!$error && $_POST) {
|
|||
if ($empty) {
|
||||
echo "<p class='message'>" . lang('No commands to execute.') . "\n";
|
||||
}
|
||||
//! MS SQL - SET SHOWPLAN_ALL OFF
|
||||
} else {
|
||||
echo "<p class='error'>" . upload_error($query) . "\n";
|
||||
}
|
||||
|
@ -142,7 +145,7 @@ echo h($q);
|
|||
|
||||
<p>
|
||||
<?php
|
||||
if (!ini_get("file_uploads")) {
|
||||
if (!ini_bool("file_uploads")) {
|
||||
echo lang('File uploads are disabled.');
|
||||
} else { ?>
|
||||
<?php echo lang('File upload'); ?>: <input type="file" name="sql_file">
|
||||
|
@ -164,7 +167,7 @@ if ($history) {
|
|||
print_fieldset("history", lang('History'), $_GET["history"] != "");
|
||||
foreach ($history as $key => $val) {
|
||||
//! save and display timestamp
|
||||
echo '<a href="' . h(ME . "sql=&history=$key") . '">' . lang('Edit') . '</a> <code class="jush-sql">' . shorten_utf8(ltrim(str_replace("\n", " ", str_replace("\r", "", preg_replace('~^(#|-- ).*~m', '', $val)))), 80, "</code>") . "<br>\n";
|
||||
echo '<a href="' . h(ME . "sql=&history=$key") . '">' . lang('Edit') . "</a> <code class='jush-$driver'>" . shorten_utf8(ltrim(str_replace("\n", " ", str_replace("\r", "", preg_replace('~^(#|-- ).*~m', '', $val)))), 80, "</code>") . "<br>\n";
|
||||
}
|
||||
echo "<input type='submit' name='clear' value='" . lang('Clear') . "'>\n";
|
||||
echo "</div></fieldset>\n";
|
||||
|
|
|
@ -4,26 +4,28 @@ a:visited { color: navy; }
|
|||
a:hover { color: red; }
|
||||
h1 { font-size: 150%; margin: 0; padding: .8em 1em; border-bottom: 1px solid #999; font-weight: normal; color: #777; background: #eee; }
|
||||
h2 { font-size: 150%; margin: 0 0 20px -18px; padding: .8em 1em; border-bottom: 1px solid #000; color: #000; font-weight: normal; background: #ddf; }
|
||||
h3 { font-weight: normal; font-size: 130%; margin: .8em 0; }
|
||||
h3 { font-weight: normal; font-size: 130%; margin: 1em 0 0; }
|
||||
form { margin: 0; }
|
||||
table { margin: 1em 20px .8em 0; border: 0; border-top: 1px solid #999; border-left: 1px solid #999; font-size: 90%; }
|
||||
td, th { margin-bottom: 1em; border: 0; border-right: 1px solid #999; border-bottom: 1px solid #999; padding: .2em .3em; }
|
||||
table { margin: 1em 20px 0 0; border: 0; border-top: 1px solid #999; border-left: 1px solid #999; font-size: 90%; }
|
||||
td, th { border: 0; border-right: 1px solid #999; border-bottom: 1px solid #999; padding: .2em .3em; }
|
||||
th { background: #eee; text-align: left; }
|
||||
thead th { text-align: center; }
|
||||
thead td, thead th { background: #ddf; }
|
||||
fieldset { display: inline; vertical-align: top; padding: .5em .8em; margin: 0 .5em .5em 0; border: 1px solid #999; }
|
||||
p { margin: 0 20px 1em 0; }
|
||||
fieldset { display: inline; vertical-align: top; padding: .5em .8em; margin: .8em .5em 0 0; border: 1px solid #999; }
|
||||
p { margin: .8em 20px 0 0; }
|
||||
img { vertical-align: middle; border: 0; }
|
||||
td img { max-width: 200px; max-height: 200px; }
|
||||
code { background: #eee; }
|
||||
tr:hover td, tr:hover th { background: #ddf; }
|
||||
pre { margin: 1em 0 0; }
|
||||
.version { color: #777; font-size: 67%; }
|
||||
.js .hidden { display: none; }
|
||||
.nowrap td, .nowrap th, td.nowrap { white-space: pre; }
|
||||
.wrap td { white-space: normal; }
|
||||
.error { color: red; background: #fee; }
|
||||
.error b { background: #fff; font-weight: normal; }
|
||||
.message { color: green; background: #efe; }
|
||||
.error, .message { padding: .5em .8em; margin: 0 20px 1em 0; }
|
||||
.error, .message { padding: .5em .8em; margin: 1em 20px 0 0; }
|
||||
.char { color: #007F00; }
|
||||
.date { color: #7F007F; }
|
||||
.enum { color: #007F7F; }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Adminer specific functions
|
||||
|
||||
/** Load syntax highlighting
|
||||
* @param string first three characters of MySQL version
|
||||
* @param string first three characters of database system version
|
||||
*/
|
||||
function bodyLoad(version) {
|
||||
var jushRoot = '../externals/jush/';
|
||||
|
@ -10,6 +10,7 @@ function bodyLoad(version) {
|
|||
script.onload = function () {
|
||||
if (window.jush) { // IE runs in case of an error too
|
||||
jush.create_links = ' target="_blank"';
|
||||
jush.urls.pgsql[0] = 'http://www.postgresql.org/docs/' + version + '/static/$key';
|
||||
jush.urls.sql[0] = 'http://dev.mysql.com/doc/refman/' + version + '/en/$key';
|
||||
jush.urls.sqlset[0] = jush.urls.sql[0];
|
||||
jush.urls.sqlstatus[0] = jush.urls.sql[0];
|
||||
|
@ -26,8 +27,6 @@ function bodyLoad(version) {
|
|||
document.body.appendChild(script);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Get value of select
|
||||
* @param HTMLSelectElement
|
||||
* @return string
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 318 B After Width: | Height: | Size: 318 B |
|
@ -27,7 +27,7 @@ function cookie(assign, days, params) {
|
|||
function verifyVersion() {
|
||||
cookie('adminer_version=0', 1);
|
||||
var script = document.createElement('script');
|
||||
script.src = 'https://adminer.svn.sourceforge.net/svnroot/adminer/trunk/version.js';
|
||||
script.src = 'https://www.adminer.org/version.php';
|
||||
document.body.appendChild(script);
|
||||
}
|
||||
|
||||
|
@ -83,6 +83,21 @@ function tableClick(event) {
|
|||
el.onclick && el.onclick();
|
||||
}
|
||||
|
||||
/** Set HTML code of an element
|
||||
* @param string
|
||||
* @param string undefined to set parentNode to
|
||||
*/
|
||||
function setHtml(id, html) {
|
||||
var el = document.getElementById(id);
|
||||
if (el) {
|
||||
if (html == undefined) {
|
||||
el.parentNode.innerHTML = ' ';
|
||||
} else {
|
||||
el.innerHTML = html;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Add row in select fieldset
|
||||
|
|
|
@ -6,21 +6,21 @@ if (!$fields) {
|
|||
}
|
||||
$table_status = ($fields ? table_status($TABLE) : array());
|
||||
|
||||
page_header(($fields && !isset($table_status["Rows"]) ? lang('View') : lang('Table')) . ": " . h($TABLE), $error);
|
||||
page_header(($fields && $table_status["Engine"] == "VIEW" ? lang('View') : lang('Table')) . ": " . h($TABLE), $error);
|
||||
$adminer->selectLinks($table_status);
|
||||
|
||||
if ($fields) {
|
||||
echo "<table cellspacing='0'>\n";
|
||||
echo "<thead><tr><th>" . lang('Column') . "<td>" . lang('Type') . "<td>" . lang('Comment') . "</thead>\n";
|
||||
echo "<thead><tr><th>" . lang('Column') . "<td>" . lang('Type') . (support("comment") ? "<td>" . lang('Comment') : "") . "</thead>\n";
|
||||
foreach ($fields as $field) {
|
||||
echo "<tr" . odd() . "><th>" . h($field["field"]);
|
||||
echo "<td>" . h($field["full_type"]) . ($field["null"] ? " <i>NULL</i>" : "") . ($field["auto_increment"] ? " <i>" . lang('Auto Increment') . "</i>" : "");
|
||||
echo "<td>" . nbsp($field["comment"]);
|
||||
echo (support("comment") ? "<td>" . nbsp($field["comment"]) : "");
|
||||
echo "\n";
|
||||
}
|
||||
echo "</table>\n";
|
||||
|
||||
if (isset($table_status["Rows"])) {
|
||||
if ($table_status["Engine"] != "VIEW") {
|
||||
echo "<h3>" . lang('Indexes') . "</h3>\n";
|
||||
$indexes = indexes($TABLE);
|
||||
if ($indexes) {
|
||||
|
@ -37,7 +37,7 @@ if ($fields) {
|
|||
}
|
||||
echo '<p><a href="' . h(ME) . 'indexes=' . urlencode($TABLE) . '">' . lang('Alter indexes') . "</a>\n";
|
||||
|
||||
if ($table_status["Engine"] == "InnoDB") {
|
||||
if (fk_support($table_status)) {
|
||||
echo "<h3>" . lang('Foreign keys') . "</h3>\n";
|
||||
$foreign_keys = foreign_keys($TABLE);
|
||||
if ($foreign_keys) {
|
||||
|
@ -52,16 +52,18 @@ if ($fields) {
|
|||
}
|
||||
echo "</table>\n";
|
||||
}
|
||||
echo '<p><a href="' . h(ME) . 'foreign=' . urlencode($TABLE) . '">' . lang('Add foreign key') . "</a>\n";
|
||||
if ($driver != "sqlite") {
|
||||
echo '<p><a href="' . h(ME) . 'foreign=' . urlencode($TABLE) . '">' . lang('Add foreign key') . "</a>\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($connection->server_info >= 5) {
|
||||
if (support("trigger")) {
|
||||
echo "<h3>" . lang('Triggers') . "</h3>\n";
|
||||
$result = $connection->query("SHOW TRIGGERS LIKE " . $connection->quote(addcslashes($TABLE, "%_")));
|
||||
if ($result->num_rows) {
|
||||
$triggers = triggers($TABLE);
|
||||
if ($triggers) {
|
||||
echo "<table cellspacing='0'>\n";
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
echo "<tr valign='top'><td>$row[Timing]<td>$row[Event]<th>" . h($row["Trigger"]) . "<td><a href='" . h(ME . 'trigger=' . urlencode($TABLE) . '&name=' . urlencode($row["Trigger"])) . "'>" . lang('Alter') . "</a>\n";
|
||||
foreach ($triggers as $key => $val) {
|
||||
echo "<tr valign='top'><td>$val[0]<td>$val[1]<th>" . h($key) . "<td><a href='" . h(ME . 'trigger=' . urlencode($TABLE) . '&name=' . urlencode($key)) . "'>" . lang('Alter') . "</a>\n";
|
||||
}
|
||||
echo "</table>\n";
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ $trigger_event = array("INSERT", "UPDATE", "DELETE");
|
|||
$dropped = false;
|
||||
if ($_POST && !$error && in_array($_POST["Timing"], $trigger_time) && in_array($_POST["Event"], $trigger_event)) {
|
||||
$dropped = drop_create(
|
||||
"DROP TRIGGER " . idf_escape($_GET["name"]),
|
||||
"CREATE TRIGGER " . idf_escape($_POST["Trigger"]) . " $_POST[Timing] $_POST[Event] ON " . idf_escape($TABLE) . " FOR EACH ROW\n$_POST[Statement]",
|
||||
"DROP TRIGGER " . idf_escape($_GET["name"]) . ($driver == "pgsql" ? " ON " . idf_escape($TABLE) : ""),
|
||||
"CREATE TRIGGER " . idf_escape($_POST["Trigger"]) . " $_POST[Timing] $_POST[Event] ON " . idf_escape($TABLE) . " FOR EACH ROW\n$_POST[Statement]", //! FOR EACH STATEMENT
|
||||
ME . "table=" . urlencode($TABLE),
|
||||
lang('Trigger has been dropped.'),
|
||||
lang('Trigger has been altered.'),
|
||||
|
@ -22,8 +22,7 @@ $row = array("Trigger" => $TABLE . "_bi");
|
|||
if ($_POST) {
|
||||
$row = $_POST;
|
||||
} elseif ($_GET["name"] != "") {
|
||||
$result = $connection->query("SHOW TRIGGERS WHERE `Trigger` = " . $connection->quote($_GET["name"]));
|
||||
$row = $result->fetch_assoc();
|
||||
$row = trigger($_GET["name"]);
|
||||
}
|
||||
?>
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ if ($_POST) {
|
|||
$row = $_POST;
|
||||
$grants = $new_grants;
|
||||
} else {
|
||||
$row = $_GET + array("host" => $connection->result($connection->query("SELECT SUBSTRING_INDEX(CURRENT_USER, '@', -1)"))); // create user on the same domain by default
|
||||
$row = $_GET + array("host" => $connection->result("SELECT SUBSTRING_INDEX(CURRENT_USER, '@', -1)")); // create user on the same domain by default
|
||||
$row["pass"] = $old_pass;
|
||||
$row["hashed"] = true;
|
||||
$grants[""] = true;
|
||||
|
|
|
@ -5,7 +5,7 @@ if ($_POST && !$error) {
|
|||
$dropped = drop_create(
|
||||
"DROP VIEW " . idf_escape($TABLE),
|
||||
"CREATE VIEW " . idf_escape($_POST["name"]) . " AS\n$_POST[select]",
|
||||
substr(ME, 0, -1),
|
||||
($_POST["drop"] ? substr(ME, 0, -1) : ME . "table=" . urlencode($_POST["name"])),
|
||||
lang('View has been dropped.'),
|
||||
lang('View has been altered.'),
|
||||
lang('View has been created.'),
|
||||
|
|
10
changes.txt
10
changes.txt
|
@ -1,3 +1,13 @@
|
|||
Adminer 3.0.0-dev:
|
||||
Drivers for MS SQL, SQLite, PostgreSQL
|
||||
Show number of tables in server overview
|
||||
Allow concurrent logins on the same server
|
||||
Operator LIKE %%
|
||||
Remember export parameters in cookie
|
||||
Allow semicolon as CSV separator
|
||||
Defer table information in database overview to JavaScript (performance)
|
||||
Big tables optimizations (performance)
|
||||
|
||||
Adminer 2.3.2 (released 2010-04-21):
|
||||
Fix COUNT(*) link
|
||||
Fix Save and continue edit
|
||||
|
|
49
compile.php
49
compile.php
|
@ -138,7 +138,7 @@ function php_shrink($input) {
|
|||
} elseif ($token[0] === T_VARIABLE && !isset($special_variables[$token[1]])) {
|
||||
$token[1] = '$' . $short_variables[$token[1]];
|
||||
}
|
||||
if (isset($set[substr($output, -1)]) || isset($set[$token[1]{0}])) {
|
||||
if (isset($set[substr($output, -1)]) || isset($set[$token[1][0]])) {
|
||||
$space = '';
|
||||
}
|
||||
$output .= $space . $token[1];
|
||||
|
@ -157,10 +157,16 @@ function compile_file($match) {
|
|||
return call_user_func($match[2], file_get_contents(dirname(__FILE__) . "/$project/$match[1]"));
|
||||
}
|
||||
|
||||
$DRIVER = "";
|
||||
if (file_exists(dirname(__FILE__) . "/adminer/drivers/" . $_SERVER["argv"][1] . ".inc.php")) {
|
||||
$DRIVER = $_SERVER["argv"][1];
|
||||
array_shift($_SERVER["argv"]);
|
||||
}
|
||||
|
||||
unset($_COOKIE["adminer_lang"]);
|
||||
$_SESSION["lang"] = $_SERVER["argv"][1]; // Adminer functions read language from session
|
||||
include dirname(__FILE__) . "/adminer/include/lang.inc.php";
|
||||
if (isset($_SESSION["lang"])) {
|
||||
include dirname(__FILE__) . "/adminer/include/lang.inc.php";
|
||||
if (isset($_SERVER["argv"][2]) || !isset($langs[$_SESSION["lang"]])) {
|
||||
echo "Usage: php compile.php [lang]\nPurpose: Compile adminer[-lang].php and editor[-lang].php.\n";
|
||||
exit(1);
|
||||
|
@ -168,11 +174,44 @@ if (isset($_SESSION["lang"])) {
|
|||
include dirname(__FILE__) . "/adminer/lang/$_SESSION[lang].inc.php";
|
||||
}
|
||||
|
||||
// check function definition in drivers
|
||||
$filename = dirname(__FILE__) . "/adminer/drivers/mysql.inc.php";
|
||||
preg_match_all('~\\bfunction ([^(]+)~', file_get_contents($filename), $matches); //! respect context (extension, class)
|
||||
$functions = array_combine($matches[1], $matches[0]);
|
||||
unset($functions["__destruct"], $functions["Min_DB"], $functions["Min_Result"]);
|
||||
foreach (glob(dirname(__FILE__) . "/adminer/drivers/" . ($DRIVER ? $DRIVER : "*") . ".inc.php") as $filename) {
|
||||
if ($filename != "mysql.inc.php") {
|
||||
$file = file_get_contents($filename);
|
||||
foreach ($functions as $val) {
|
||||
if (!strpos($file, "$val(")) {
|
||||
echo "Missing $val in $filename\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (array("adminer", "editor") as $project) {
|
||||
$lang_ids = array(); // global variable simplifies usage in a callback function
|
||||
$file = file_get_contents(dirname(__FILE__) . "/$project/index.php");
|
||||
if ($DRIVER && $DRIVER != "mysql") {
|
||||
$_GET[$DRIVER] = true; // to load the driver
|
||||
include_once dirname(__FILE__) . "/adminer/drivers/$DRIVER.inc.php";
|
||||
foreach (array("view", "event", "privileges", "user", "processlist", "variables", "trigger") as $feature) {
|
||||
if (!support($feature)) {
|
||||
$file = str_replace("} elseif (isset(\$_GET[\"$feature\"])) {\n\tinclude \"./$feature.inc.php\";\n", "", $file);
|
||||
}
|
||||
}
|
||||
if (!support("routine")) {
|
||||
$file = str_replace("} elseif (isset(\$_GET[\"procedure\"])) {\n\tinclude \"./procedure.inc.php\";\n", "", $file);
|
||||
$file = str_replace("} elseif (isset(\$_GET[\"call\"])) {\n\tinclude \"./call.inc.php\";\n", "", $file);
|
||||
$file = str_replace("if (isset(\$_GET[\"callf\"])) {\n\t\$_GET[\"call\"] = \$_GET[\"callf\"];\n}\nif (isset(\$_GET[\"function\"])) {\n\t\$_GET[\"procedure\"] = \$_GET[\"function\"];\n}\n", "", $file);
|
||||
}
|
||||
}
|
||||
$file = preg_replace_callback('~\\b(include|require) "([^"]*)";~', 'put_file', $file);
|
||||
$file = str_replace('include "../adminer/include/coverage.inc.php";', '', $file);
|
||||
if ($DRIVER) {
|
||||
$file = preg_replace('(include "../adminer/drivers/(?!' . preg_quote($DRIVER) . ').*\\s*)', '', $file);
|
||||
}
|
||||
$file = preg_replace_callback('~\\b(include|require) "([^"]*)";~', 'put_file', $file); // bootstrap.inc.php
|
||||
$file = preg_replace_callback("~lang\\('((?:[^\\\\']+|\\\\.)*)'([,)])~s", 'lang_ids', $file);
|
||||
$file = preg_replace_callback('~\\b(include|require) "([^"]*\\$LANG.inc.php)";~', 'put_file_lang', $file);
|
||||
|
@ -187,11 +226,11 @@ foreach (array("adminer", "editor") as $project) {
|
|||
$replace = 'h(preg_replace("~\\\\\\\\?.*~", "", $_SERVER["REQUEST_URI"])) . "?file=\\1&version=' . $VERSION;
|
||||
$file = preg_replace('~\\.\\./adminer/static/(default\\.css|functions\\.js|favicon\\.ico)~', '<?php echo ' . $replace . '"; ?>', $file);
|
||||
$file = preg_replace('~\\.\\./adminer/static/([^\'"]*)~', '" . ' . $replace, $file);
|
||||
$file = str_replace("../externals/jush/", "https://jush.svn.sourceforge.net/svnroot/jush/trunk/", $file); // mixed-content warning if Adminer runs on HTTPS and external files on HTTP
|
||||
$file = str_replace("../externals/jush/", "https://www.adminer.org/static/", $file);
|
||||
$file = preg_replace("~<\\?php\\s*\\?>\n?|\\?>\n?<\\?php~", '', $file);
|
||||
$file = php_shrink($file);
|
||||
|
||||
$filename = $project . ($_SESSION["lang"] ? "-$_SESSION[lang]" : "") . ".php"; // "$project-$VERSION"
|
||||
$filename = $project . ($DRIVER ? "-$DRIVER" : "") . ($_SESSION["lang"] ? "-$_SESSION[lang]" : "") . ".php"; // . "-$VERSION"
|
||||
fwrite(fopen($filename, "w"), $file); // file_put_contents() since PHP 5
|
||||
echo "$filename created.\n";
|
||||
echo "$filename created (" . strlen($file) . " B).\n";
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ function xhtml_open_tags($s) {
|
|||
$return = array();
|
||||
preg_match_all('~<([^>]+)~', $s, $matches);
|
||||
foreach ($matches[1] as $val) {
|
||||
if ($val{0} == "/") {
|
||||
if ($val[0] == "/") {
|
||||
array_pop($return);
|
||||
} elseif (substr($val, -1) != "/") {
|
||||
$return[] = $val;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?php
|
||||
page_header(lang('Server'), "", null);
|
||||
page_header(lang('Server'), "", false);
|
||||
|
||||
?>
|
||||
<form action=""><p>
|
||||
<?php echo SID_FORM; ?>
|
||||
<?php hidden_fields_get(); ?>
|
||||
<input name="where[0][val]" value="<?php echo h($_GET["where"][0]["val"]); ?>">
|
||||
<input type="submit" value="<?php echo lang('Search'); ?>" />
|
||||
</form>
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
<?php
|
||||
class Adminer {
|
||||
var $operators = array("<=", ">=");
|
||||
var $values = array(); // protected
|
||||
var $_values = array();
|
||||
|
||||
function name() {
|
||||
return lang('Editor');
|
||||
}
|
||||
|
||||
//! driver
|
||||
|
||||
function credentials() {
|
||||
return array(); // default INI settings
|
||||
}
|
||||
|
@ -19,15 +21,15 @@ class Adminer {
|
|||
global $connection;
|
||||
$dbs = get_databases(false);
|
||||
return (!$dbs
|
||||
? $connection->result($connection->query("SELECT SUBSTRING_INDEX(CURRENT_USER, '@', 1)")) // username without the database list
|
||||
? $connection->result("SELECT SUBSTRING_INDEX(CURRENT_USER, '@', 1)") // username without the database list
|
||||
: $dbs[(information_schema($dbs[0]) ? 1 : 0)] // first available database
|
||||
);
|
||||
}
|
||||
|
||||
function loginForm($username) {
|
||||
function loginForm() {
|
||||
?>
|
||||
<table cellspacing="0">
|
||||
<tr><th><?php echo lang('Username'); ?><td><input type="hidden" name="server" value=""><input name="username" value="<?php echo h($username); ?>">
|
||||
<tr><th><?php echo lang('Username'); ?><td><input type="hidden" name="driver" value="server"><input type="hidden" name="server" value=""><input name="username" value="<?php echo h($_GET["username"]); ?>">
|
||||
<tr><th><?php echo lang('Password'); ?><td><input type="password" name="password">
|
||||
</table>
|
||||
<?php
|
||||
|
@ -59,13 +61,13 @@ class Adminer {
|
|||
function backwardKeys($table, $tableName) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
if ($connection->server_info >= 5) { //! requires MySQL 5
|
||||
$result = $connection->query("SELECT TABLE_NAME, CONSTRAINT_NAME, COLUMN_NAME, REFERENCED_COLUMN_NAME
|
||||
$result = $connection->query("SELECT TABLE_NAME, CONSTRAINT_NAME, COLUMN_NAME, REFERENCED_COLUMN_NAME
|
||||
FROM information_schema.KEY_COLUMN_USAGE
|
||||
WHERE TABLE_SCHEMA = " . $connection->quote($this->database()) . "
|
||||
AND REFERENCED_TABLE_SCHEMA = " . $connection->quote($this->database()) . "
|
||||
AND REFERENCED_TABLE_NAME = " . $connection->quote($table) . "
|
||||
ORDER BY ORDINAL_POSITION");
|
||||
if ($result) { //! requires MySQL 5
|
||||
while ($row = $result->fetch_assoc()) {
|
||||
$return[$row["TABLE_NAME"]]["keys"][$row["CONSTRAINT_NAME"]][$row["COLUMN_NAME"]] = $row["REFERENCED_COLUMN_NAME"];
|
||||
}
|
||||
|
@ -93,7 +95,7 @@ ORDER BY ORDINAL_POSITION");
|
|||
foreach ($cols as $column => $val) {
|
||||
$link .= where_link($i++, $column, $row[$val]);
|
||||
}
|
||||
echo "<a href='" . h($link) . "'>$backwardKey[name]</a>";
|
||||
echo "<a href='" . h($link) . "'>" . h($backwardKey["name"]) . "</a>";
|
||||
$link = ME . 'edit=' . urlencode($table);
|
||||
foreach ($cols as $column => $val) {
|
||||
$link .= "&set" . urlencode("[" . bracket_escape($column) . "]") . "=" . urlencode($row[$val]);
|
||||
|
@ -119,7 +121,6 @@ ORDER BY ORDINAL_POSITION");
|
|||
}
|
||||
|
||||
function rowDescriptions($rows, $foreignKeys) {
|
||||
global $connection;
|
||||
$return = $rows;
|
||||
foreach ($rows[0] as $key => $val) {
|
||||
foreach ((array) $foreignKeys[$key] as $foreignKey) {
|
||||
|
@ -133,7 +134,7 @@ ORDER BY ORDINAL_POSITION");
|
|||
$ids[$row[$key]] = exact_value($row[$key]);
|
||||
}
|
||||
// uses constant number of queries to get the descriptions, join would be complex, multiple queries would be slow
|
||||
$descriptions = $this->values[$foreignKey["table"]];
|
||||
$descriptions = $this->_values[$foreignKey["table"]];
|
||||
if (!$descriptions) {
|
||||
$descriptions = get_key_vals("SELECT $id, $name FROM " . idf_escape($foreignKey["table"]) . " WHERE $id IN (" . implode(", ", $ids) . ")");
|
||||
}
|
||||
|
@ -153,7 +154,7 @@ ORDER BY ORDINAL_POSITION");
|
|||
|
||||
function selectVal($val, $link, $field) {
|
||||
$return = ($val == "<i>NULL</i>" ? " " : $val);
|
||||
if (ereg('blob|binary', $field["type"]) && !is_utf8($val)) {
|
||||
if (ereg('binary|blob|bytea', $field["type"]) && !is_utf8($val)) {
|
||||
$return = lang('%d byte(s)', strlen($val));
|
||||
if (ereg("^(GIF|\xFF\xD8\xFF|\x89\x50\x4E\x47\x0D\x0A\x1A\x0A)", $val)) { // GIF|JPG|PNG, getimagetype() works with filename
|
||||
$return = "<img src='$link' alt='$return'>";
|
||||
|
@ -181,39 +182,47 @@ ORDER BY ORDINAL_POSITION");
|
|||
}
|
||||
|
||||
function selectColumnsPrint($select, $columns) {
|
||||
//! allow grouping functions by indexes
|
||||
// can allow grouping functions by indexes
|
||||
}
|
||||
|
||||
function selectSearchPrint($where, $columns, $indexes) {
|
||||
//! foreign keys
|
||||
$where = (array) $_GET["where"];
|
||||
echo '<fieldset><legend>' . lang('Search') . "</legend><div>\n";
|
||||
$keys = array();
|
||||
foreach ((array) $_GET["where"] as $key => $val) {
|
||||
foreach ($where as $key => $val) {
|
||||
$keys[$val["col"]] = $key;
|
||||
}
|
||||
$i = -1;
|
||||
foreach ($columns as $name => $desc) {
|
||||
$key = $keys[$name];
|
||||
$options = $this->foreignKeyOptions($_GET["select"], $name);
|
||||
if ($options) {
|
||||
echo "<div>" . h($desc) . "<input type='hidden' name='where[$i][col]' value='" . h($name) . "'><input type='hidden' name='where[$i][op]' value='='>: <select name='where[$i][val]'>" . optionlist($options, $_GET["where"][$key]["val"], true) . "</select></div>\n";
|
||||
$i = 0;
|
||||
foreach (fields($_GET["select"]) as $name => $field) {
|
||||
if (ereg("enum", $field["type"])) { //! set - uses 1 << $i and FIND_IN_SET()
|
||||
$desc = $columns[$name];
|
||||
$key = $keys[$name];
|
||||
$i--;
|
||||
echo "<div>" . h($desc) . "<input type='hidden' name='where[$i][col]' value='" . h($name) . "'>:";
|
||||
enum_input("checkbox", "where[$i][val][]", $field, (array) $where[$key]["val"]); //! impossible to search for NULL
|
||||
echo "</div>\n";
|
||||
unset($columns[$name]);
|
||||
}
|
||||
}
|
||||
foreach ($columns as $name => $desc) {
|
||||
$options = $this->_foreignKeyOptions($_GET["select"], $name);
|
||||
if ($options) {
|
||||
$key = $keys[$name];
|
||||
$i--;
|
||||
echo "<div>" . h($desc) . "<input type='hidden' name='where[$i][col]' value='" . h($name) . "'><input type='hidden' name='where[$i][op]' value='='>: <select name='where[$i][val]'>" . optionlist($options, $where[$key]["val"], true) . "</select></div>\n";
|
||||
unset($columns[$name]);
|
||||
if (isset($key)) {
|
||||
unset($_GET["where"][$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
$i = 0;
|
||||
foreach ((array) $_GET["where"] as $val) {
|
||||
if ("$val[col]$val[val]" != "") {
|
||||
echo "<div><select name='where[$i][col]'><option value=''>" . lang('(anywhere)') . optionlist($columns, $val["col"], true) . "</select>";
|
||||
foreach ($where as $val) {
|
||||
if ($columns[$val["col"]] && "$val[col]$val[val]" != "") {
|
||||
echo "<div><select name='where[$i][col]'><option value=''>(" . lang('anywhere') . ")" . optionlist($columns, $val["col"], true) . "</select>";
|
||||
echo html_select("where[$i][op]", array(-1 => "") + $this->operators, $val["op"]);
|
||||
echo "<input name='where[$i][val]' value='" . h($val["val"]) . "'></div>\n";
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
echo "<div><select name='where[$i][col]' onchange='selectAddRow(this);'><option value=''>" . lang('(anywhere)') . optionlist($columns, null, true) . "</select>";
|
||||
echo "<div><select name='where[$i][col]' onchange='selectAddRow(this);'><option value=''>(" . lang('anywhere') . ")" . optionlist($columns, null, true) . "</select>";
|
||||
echo html_select("where[$i][op]", array(-1 => "") + $this->operators);
|
||||
echo "<input name='where[$i][val]'></div>\n";
|
||||
echo "</div></fieldset>\n";
|
||||
|
@ -260,7 +269,7 @@ ORDER BY ORDINAL_POSITION");
|
|||
echo lang('Subject') . ": <input name='email_subject' value='" . h($_POST["email_subject"]) . "'>\n";
|
||||
echo "<p><textarea name='email_message' rows='15' cols='75'>" . h($_POST["email_message"] . ($_POST["email_append"] ? '{$' . "$_POST[email_addition]}" : "")) . "</textarea><br>\n";
|
||||
echo html_select("email_addition", $columns, $_POST["email_addition"]) . "<input type='submit' name='email_append' value='" . lang('Insert') . "'>\n"; //! JavaScript
|
||||
echo "<p><input type='file' name='email_files[]' onchange=\"var el = this.cloneNode(true); el.value = ''; this.parentNode.appendChild(el); this.onchange = function () { };\">";
|
||||
echo "<p>" . lang('Attachments') . ": <input type='file' name='email_files[]' onchange=\"var el = this.cloneNode(true); el.value = ''; this.parentNode.appendChild(el); this.onchange = function () { };\">";
|
||||
echo "<p>" . (count($emailFields) == 1 ? '<input type="hidden" name="email_field" value="' . h(key($emailFields)) . '">' : html_select("email_field", $emailFields));
|
||||
echo "<input type='submit' name='email' value='" . lang('Send') . "' onclick=\"return this.form['delete'].onclick();\">\n";
|
||||
echo "</div></fieldset>\n";
|
||||
|
@ -273,15 +282,21 @@ ORDER BY ORDINAL_POSITION");
|
|||
|
||||
function selectSearchProcess($fields, $indexes) {
|
||||
$return = array();
|
||||
foreach ((array) $_GET["where"] as $key => $val) {
|
||||
$col = $val["col"];
|
||||
if (($key < 0 ? "" : $col) . $val["val"] != "") {
|
||||
foreach ((array) $_GET["where"] as $key => $where) {
|
||||
$col = $where["col"];
|
||||
$op = $where["op"];
|
||||
$val = $where["val"];
|
||||
if (($key < 0 ? "" : $col) . $val != "") {
|
||||
$conds = array();
|
||||
foreach (($col != "" ? array($col => $fields[$col]) : $fields) as $name => $field) {
|
||||
if ($col != "" || is_numeric($val["val"]) || !ereg('int|float|double|decimal', $field["type"])) {
|
||||
$text_type = ereg('char|text|enum|set', $field["type"]);
|
||||
$value = $this->processInput($field, ($text_type && ereg('^[^%]+$', $val["val"]) ? "%$val[val]%" : $val["val"]));
|
||||
$conds[] = idf_escape($name) . ($value == "NULL" ? " IS" . ($val["op"] == ">=" ? " NOT" : "") : (in_array($val["op"], $this->operators) ? " $val[op]" : ($val["op"] != "=" && $text_type ? " LIKE" : " ="))) . " $value"; //! can issue "Illegal mix of collations" for columns in other character sets - solve by CONVERT($name using utf8)
|
||||
if ($col != "" || is_numeric($val) || !ereg('int|float|double|decimal', $field["type"])) {
|
||||
if ($col != "" && $field["type"] == "enum") {
|
||||
$conds[] = idf_escape($name) . " IN (" . implode(", ", array_map('intval', $val)) . ")";
|
||||
} else {
|
||||
$text_type = ereg('char|text|enum|set', $field["type"]);
|
||||
$value = $this->processInput($field, ($text_type && ereg('^[^%]+$', $val) ? "%$val%" : $val));
|
||||
$conds[] = idf_escape($name) . ($value == "NULL" ? " IS" . ($op == ">=" ? " NOT" : "") : (in_array($op, $this->operators) ? " $op" : ($op != "=" && $text_type ? " LIKE" : " ="))) . " $value"; //! can issue "Illegal mix of collations" for columns in other character sets - solve by CONVERT($name using utf8)
|
||||
}
|
||||
}
|
||||
}
|
||||
$return[] = ($conds ? "(" . implode(" OR ", $conds) . ")" : "0");
|
||||
|
@ -332,8 +347,7 @@ ORDER BY ORDINAL_POSITION");
|
|||
if ($_POST["all"] || $_POST["check"]) {
|
||||
$field = idf_escape($_POST["email_field"]);
|
||||
$subject = $_POST["email_subject"];
|
||||
$eol = (strncasecmp(PHP_OS, "win", 3) ? "\n" : "\r\n");
|
||||
$message = str_replace("\n", $eol, wordwrap(str_replace("\r", "", "$_POST[email_message]\n")));
|
||||
$message = $_POST["email_message"];
|
||||
preg_match_all('~\\{\\$([a-z0-9_]+)\\}~i', "$subject.$message", $matches); // allows {$name} in subject or message
|
||||
$result = $connection->query("SELECT DISTINCT $field" . ($matches[1] ? ", " . implode(", ", array_map('idf_escape', array_unique($matches[1]))) : "") . " FROM " . idf_escape($_GET["select"])
|
||||
. " WHERE $field IS NOT NULL AND $field != ''"
|
||||
|
@ -344,37 +358,14 @@ ORDER BY ORDINAL_POSITION");
|
|||
while ($row = $result->fetch_assoc()) {
|
||||
$rows[] = $row;
|
||||
}
|
||||
$boundary = uniqid("boundary");
|
||||
$attachments = "";
|
||||
$email_files = $_FILES["email_files"];
|
||||
foreach ($email_files["error"] as $key => $val) {
|
||||
if (!$val) {
|
||||
$attachments .= "--$boundary$eol"
|
||||
. "Content-Type: " . str_replace("\n", "", $email_files["type"][$key]) . $eol
|
||||
. "Content-Disposition: attachment; filename=\"" . preg_replace('~["\\n]~', '', $email_files["name"][$key]) . "\"$eol"
|
||||
. "Content-Transfer-Encoding: base64$eol"
|
||||
. $eol . chunk_split(base64_encode(file_get_contents($email_files["tmp_name"][$key])), 76, $eol) . $eol
|
||||
;
|
||||
}
|
||||
}
|
||||
$beginning = "";
|
||||
$headers = "Content-Type: text/plain; charset=utf-8$eol" . "Content-Transfer-Encoding: 8bit";
|
||||
if ($attachments) {
|
||||
$attachments .= "--$boundary--$eol";
|
||||
$beginning = "--$boundary$eol$headers$eol$eol";
|
||||
$headers = "Content-Type: multipart/mixed; boundary=\"$boundary\"";
|
||||
}
|
||||
$headers .= $eol . "MIME-Version: 1.0$eol" . "X-Mailer: Adminer Editor"
|
||||
. ($_POST["email_from"] ? $eol . "From: " . str_replace("\n", "", $_POST["email_from"]) : "") //! should escape display name
|
||||
;
|
||||
$fields = fields($_GET["select"]);
|
||||
foreach ($this->rowDescriptions($rows, $foreignKeys) as $row) {
|
||||
$replace = array();
|
||||
$replace = array('{\\' => '{'); // allow literal {$name}
|
||||
foreach ($matches[1] as $val) {
|
||||
$replace['{$' . "$val}"] = $this->editVal($row[$val], $fields[$val]); //! allow literal {$name}
|
||||
$replace['{$' . "$val}"] = $this->editVal($row[$val], $fields[$val]);
|
||||
}
|
||||
$email = $row[$_POST["email_field"]];
|
||||
if (is_email($email) && mail($email, email_header(strtr($subject, $replace)), $beginning . strtr($message, $replace) . $attachments, $headers)) {
|
||||
if (is_email($email) && send_email($email, strtr($subject, $replace), strtr($message, $replace), $_POST["email_from"], $_FILES["email_files"])) {
|
||||
$sent++;
|
||||
}
|
||||
}
|
||||
|
@ -391,6 +382,7 @@ ORDER BY ORDINAL_POSITION");
|
|||
|
||||
function editFunctions($field) {
|
||||
$return = array("" => ($field["null"] || $field["auto_increment"] || $field["full_type"] == "tinyint(1)" ? "" : "*"));
|
||||
//! respect driver
|
||||
if (ereg('date|time', $field["type"])) {
|
||||
$return[] = "now";
|
||||
}
|
||||
|
@ -404,7 +396,7 @@ ORDER BY ORDINAL_POSITION");
|
|||
if ($field["type"] == "enum") {
|
||||
return ($field["null"] ? "<input type='radio'$attrs value=''" . ($value || isset($_GET["select"]) ? "" : " checked") . ">" : "");
|
||||
}
|
||||
$options = $this->foreignKeyOptions($table, $field["field"]);
|
||||
$options = $this->_foreignKeyOptions($table, $field["field"]);
|
||||
if ($options) {
|
||||
return "<select$attrs>" . optionlist($options, $value, true) . "</select>";
|
||||
}
|
||||
|
@ -429,20 +421,22 @@ ORDER BY ORDINAL_POSITION");
|
|||
$return = $connection->quote($return);
|
||||
if (!ereg('varchar|text', $field["type"]) && $field["full_type"] != "tinyint(1)" && $value == "") {
|
||||
$return = "NULL";
|
||||
} elseif (ereg('^(md5|sha1)$', $function)) {
|
||||
$return = "$function($return)";
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
function dumpOutput($select) {
|
||||
function dumpOutput($select, $value = "") {
|
||||
return "";
|
||||
}
|
||||
|
||||
function dumpFormat($select) {
|
||||
return "CSV";
|
||||
function dumpFormat($select, $value = "") {
|
||||
return html_select("format", array('csv' => 'CSV,', 'csv;' => 'CSV;'), $value, $select);
|
||||
}
|
||||
|
||||
function navigation($missing) {
|
||||
global $VERSION;
|
||||
global $VERSION, $token;
|
||||
?>
|
||||
<h1>
|
||||
<a href="http://www.adminer.org/" id="h1"><?php echo $this->name(); ?></a>
|
||||
|
@ -454,7 +448,7 @@ ORDER BY ORDINAL_POSITION");
|
|||
?>
|
||||
<form action="" method="post">
|
||||
<p class="logout">
|
||||
<input type="hidden" name="token" value="<?php echo $_SESSION["tokens"][$_GET["server"]]; ?>">
|
||||
<input type="hidden" name="token" value="<?php echo $token; ?>">
|
||||
<input type="submit" name="logout" value="<?php echo lang('Logout'); ?>">
|
||||
</p>
|
||||
</form>
|
||||
|
@ -480,27 +474,25 @@ ORDER BY ORDINAL_POSITION");
|
|||
}
|
||||
}
|
||||
|
||||
function foreignKeyOptions($table, $column) { // protected
|
||||
function _foreignKeyOptions($table, $column) {
|
||||
global $connection;
|
||||
$table_status = table_status($table);
|
||||
$foreignKeys = column_foreign_keys($table);
|
||||
foreach ((array) $foreignKeys[$column] as $foreignKey) {
|
||||
if (count($foreignKey["source"]) == 1) {
|
||||
$id = idf_escape($foreignKey["target"][0]);
|
||||
$name = $this->rowDescription($foreignKey["table"]);
|
||||
if ($name != "") {
|
||||
$return = &$this->values[$foreignKey["table"]];
|
||||
$return = &$this->_values[$foreignKey["table"]];
|
||||
if (!isset($return)) {
|
||||
$return = array("" => "") + get_key_vals("SELECT $id, $name FROM " . idf_escape($foreignKey["table"]) . " ORDER BY 2 LIMIT 1001");
|
||||
if (count($return) > 1001) {
|
||||
$return = array();
|
||||
}
|
||||
$return = ($table_status["Rows"] > 1000 ? array() : array("" => "") + get_key_vals("SELECT $id, $name FROM " . idf_escape($foreignKey["table"]) . " ORDER BY 2"));
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
$adminer = (function_exists('adminer_object') ? adminer_object() : new Adminer);
|
||||
|
|
|
@ -8,16 +8,38 @@ function email_header($header) {
|
|||
return "=?UTF-8?B?" . base64_encode($header) . "?="; //! split long lines
|
||||
}
|
||||
|
||||
/** Get keys from first column and values from second
|
||||
/** Send e-mail in UTF-8
|
||||
* @param string
|
||||
* @return array
|
||||
* @param string
|
||||
* @param string
|
||||
* @param string
|
||||
* @param array
|
||||
* @return
|
||||
*/
|
||||
function get_key_vals($query) {
|
||||
global $connection;
|
||||
$return = array();
|
||||
$result = $connection->query($query);
|
||||
while ($row = $result->fetch_row()) {
|
||||
$return[$row[0]] = $row[1];
|
||||
function send_email($email, $subject, $message, $from = "", $files = array()) {
|
||||
$eol = (strncasecmp(PHP_OS, "win", 3) ? "\n" : "\r\n"); // PHP_EOL available since PHP 4.3.10 and 5.0.2
|
||||
$message = str_replace("\n", $eol, wordwrap(str_replace("\r", "", "$message\n")));
|
||||
$boundary = uniqid("boundary");
|
||||
$attachments = "";
|
||||
foreach ($files["error"] as $key => $val) {
|
||||
if (!$val) {
|
||||
$attachments .= "--$boundary$eol"
|
||||
. "Content-Type: " . str_replace("\n", "", $files["type"][$key]) . $eol
|
||||
. "Content-Disposition: attachment; filename=\"" . preg_replace('~["\\n]~', '', $files["name"][$key]) . "\"$eol"
|
||||
. "Content-Transfer-Encoding: base64$eol$eol"
|
||||
. chunk_split(base64_encode(file_get_contents($files["tmp_name"][$key])), 76, $eol) . $eol
|
||||
;
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
$beginning = "";
|
||||
$headers = "Content-Type: text/plain; charset=utf-8$eol" . "Content-Transfer-Encoding: 8bit";
|
||||
if ($attachments) {
|
||||
$attachments .= "--$boundary--$eol";
|
||||
$beginning = "--$boundary$eol$headers$eol$eol";
|
||||
$headers = "Content-Type: multipart/mixed; boundary=\"$boundary\"";
|
||||
}
|
||||
$headers .= $eol . "MIME-Version: 1.0$eol" . "X-Mailer: Adminer Editor"
|
||||
. ($from ? $eol . "From: " . str_replace("\n", "", $from) : "") //! should escape display name
|
||||
;
|
||||
return mail($email, email_header($subject), $beginning . $message . $attachments, $headers);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?php
|
||||
/** Adminer Editor - Compact MySQL editor
|
||||
/** Adminer Editor - Compact database editor
|
||||
* @link http://www.adminer.org/
|
||||
* @author Jakub Vrana, http://php.vrana.cz/
|
||||
* @copyright 2009 Jakub Vrana
|
||||
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
include "../adminer/include/bootstrap.inc.php";
|
||||
$drivers[DRIVER] = lang('Login');
|
||||
|
||||
if (isset($_GET["select"]) && ($_POST["edit"] || $_POST["clone"]) && !$_POST["save"]) {
|
||||
$_GET["edit"] = $_GET["select"];
|
||||
|
|
1
lang.php
1
lang.php
|
@ -14,6 +14,7 @@ $messages_all = array();
|
|||
foreach (array_merge(
|
||||
glob(dirname(__FILE__) . "/adminer/*.php"),
|
||||
glob(dirname(__FILE__) . "/adminer/include/*.php"),
|
||||
glob(dirname(__FILE__) . "/adminer/drivers/*.php"),
|
||||
glob(dirname(__FILE__) . "/editor/*.php"),
|
||||
glob(dirname(__FILE__) . "/editor/include/*.php")
|
||||
) as $filename) {
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/coverage.php?coverage=0</td>
|
||||
<td>coverage.php?coverage=0</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?lang=en&username=ODBC</td>
|
||||
<td>adminer/?username=ODBC&lang=en</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/</td>
|
||||
<td>adminer/?username=ODBC</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?db=adminer_test&select=albums</td>
|
||||
<td>adminer/?username=ODBC&db=adminer_test&select=albums</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?db=adminer_test&select=albums</td>
|
||||
<td>adminer/?username=ODBC&db=adminer_test&select=albums</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?db=adminer_test&edit=albums&where%5Bid%5D=2</td>
|
||||
<td>adminer/?username=ODBC&db=adminer_test&edit=albums&where%5Bid%5D=2</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?db=adminer_test&select=albums</td>
|
||||
<td>adminer/?username=ODBC&db=adminer_test&select=albums</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?db=adminer_test&select=albums</td>
|
||||
<td>adminer/?username=ODBC&db=adminer_test&select=albums</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?user=</td>
|
||||
<td>adminer/?username=ODBC&user=</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?processlist=</td>
|
||||
<td>adminer/?username=ODBC&processlist=</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?db=adminer_test&dump=</td>
|
||||
<td>adminer/?username=ODBC&db=adminer_test&dump=</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?db=adminer_test&event=</td>
|
||||
<td>adminer/?username=ODBC&db=adminer_test&event=</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?db=adminer_test&procedure=</td>
|
||||
<td>adminer/?username=ODBC&db=adminer_test&procedure=</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?db=adminer_test</td>
|
||||
<td>adminer/?username=ODBC&db=adminer_test</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?db=adminer_test&table=interprets</td>
|
||||
<td>adminer/?username=ODBC&db=adminer_test&table=interprets</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?variables=</td>
|
||||
<td>adminer/?username=ODBC&variables=</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?sql=</td>
|
||||
<td>adminer/?username=ODBC&sql=</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/editor/example.php?lang=en&username=admin</td>
|
||||
<td>editor/example.php?lang=en&username=admin</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?db=adminer_test&select=albums</td>
|
||||
<td>adminer/?username=ODBC&db=adminer_test&select=albums</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?db=adminer_test&table=interprets</td>
|
||||
<td>adminer/?username=ODBC&db=adminer_test&table=interprets</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?db=adminer_test&table=interprets&lang=en</td>
|
||||
<td>adminer/?username=ODBC&db=adminer_test&table=interprets&lang=en</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?db=adminer_test&table=albums</td>
|
||||
<td>adminer/?username=ODBC&db=adminer_test&table=albums</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?db=adminer_test&table=interprets</td>
|
||||
<td>adminer/?username=ODBC&db=adminer_test&table=interprets</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?db=adminer_test&trigger=albums</td>
|
||||
<td>adminer/?username=ODBC&db=adminer_test&trigger=albums</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?db=adminer_test&view=</td>
|
||||
<td>adminer/?username=ODBC&db=adminer_test&view=</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?db=adminer_test&edit=interprets</td>
|
||||
<td>adminer/?username=ODBC&db=adminer_test&edit=interprets</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -33,7 +33,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/?db=adminer_test&edit=albums</td>
|
||||
<td>adminer/?username=ODBC&db=adminer_test&edit=albums</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</thead><tbody>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/adminer/</td>
|
||||
<td>adminer/?username=ODBC</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -38,7 +38,7 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td>open</td>
|
||||
<td>/adminer/coverage.php</td>
|
||||
<td>coverage.php</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
|
|
32
todo.txt
32
todo.txt
|
@ -2,9 +2,7 @@ MySQL 5 BIT data type
|
|||
Transactions in export
|
||||
Create view and routine options
|
||||
Mass editation of individual rows
|
||||
Offer enum and set items in search - whisperer
|
||||
Variables editation, especially timezone
|
||||
Use event $intervals + microseconds in relative date functions
|
||||
Optionally check IP address
|
||||
Disable spell checking in SQL textareas - spellcheck="false"
|
||||
Accept Tab in SQL textareas, Ctrl+Enter to send form
|
||||
|
@ -12,14 +10,40 @@ Highlight SQL textarea, then display query inside textarea in select - may use e
|
|||
Blob download and image display in edit form (important for Editor with hidden fields in select)
|
||||
Add title to Logout, edit (in select) and select (in menu) in style "hever"
|
||||
Shift-click in checkboxes to select range
|
||||
? LIKE %% operator
|
||||
Export by GET parameters
|
||||
Only first part of big BZ2 export is readable
|
||||
? Column and table names auto-completition in SQL textarea
|
||||
? Aliasing of built-in functions can save 7 KB, function minification can save 7 KB, substitution of repetitive $a["a"] can save 4 KB, substitution of $_GET and friends can save 2 KB, JS packer can save 1 KB, not enclosing HTML attribute values can save 1.2 KB, replacing \\n by \n can save .3 KB
|
||||
? Aliasing of built-in functions can save 7 KB, function minification can save 7 KB, substitution of repetitive $a["a"] can save 4 KB, substitution of $_GET and friends can save 2 KB, aliasing of $connection->query, $connection->result and $connection->quote can save ~ 3 KB, JS packer can save 1 KB, not enclosing HTML attribute values can save 1.2 KB, replacing \\n by \n can save .3 KB
|
||||
? Branch binary_compile: LZW compression of translations can save 30 KB, LZW compression of all texts can save 11 KB, remove of base64_decode() + using chars 127-255 in minification can save 1 KB
|
||||
? AJAX editing - select page has all data to display edit form
|
||||
? MySQL geometry support
|
||||
Translations - database(s) have been dropped
|
||||
|
||||
Editor:
|
||||
JavaScript data validation - columns containing word email, url, ...
|
||||
Joining tables - PRIMARY KEY (table, joining)
|
||||
Rank, Tree structure
|
||||
Add whisperer to fields with foreign key to big table
|
||||
|
||||
SQLite:
|
||||
CREATE DATABASE - PRAGMA encoding = "UTF-8"
|
||||
Detecion of non-existing database
|
||||
DROP DATABASE by file operations
|
||||
CSV import - ON DUPLICATE KEY UPDATE
|
||||
Export - views, triggers
|
||||
Delimiter in export and SQL command
|
||||
|
||||
PostgreSQL:
|
||||
Users - SELECT * FROM pg_user
|
||||
ORDER BY COUNT(*)
|
||||
Table schema
|
||||
Export - http://www.postgresql.org/docs/8.4/static/functions-info.html
|
||||
Table status - http://www.postgresql.org/docs/8.4/static/functions-admin.html
|
||||
Column rights - http://www.postgresql.org/docs/8.4/static/functions-info.html
|
||||
Move table - ALTER TABLE SET SCHEMA
|
||||
bool in Editor
|
||||
|
||||
MS SQL:
|
||||
Rename by sp_rename
|
||||
Detection of table collation
|
||||
PDO driver
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// downloaded from repository by verifyVersion()
|
||||
// downloaded from repository by verifyVersion() before Adminer 3.0.0
|
||||
(function () { // cookie function is not defined in older versions
|
||||
var date = new Date();
|
||||
date.setDate(date.getDate() + 7); // valid for 7 days
|
||||
|
|
Loading…
Reference in a new issue